diff --git a/CHANGELOG.md b/CHANGELOG.md index 370b830e1a..9865fef896 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1341,7 +1341,7 @@ class User: @strawberry.field @staticmethod async def name(parent: strawberry.Parent[UserRow]) -> str: - return f"User Number {parent.id}" + return f"User Number {parent.id_}" @strawberry.type @@ -4197,7 +4197,7 @@ the original type was already used with that generic in the schema. Example: -```python3 +```python @strawberry.type class Query: regular: Edge[User] diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..c285d0ee23 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,15 @@ +Release type: minor + +This release changes some of the internals of Strawberry, it shouldn't +be affecting most of the users, but since we have changed the structure +of the code you might need to update your imports. + +Thankfully we also provide a codemod for this, you can run it with: + +```bash +strawberry upgrade update-imports +``` + +This release also includes additional documentation to some of +the classes, methods and functions, this is in preparation for +having the API reference in the documentation ✨ diff --git a/TWEET.md b/TWEET.md new file mode 100644 index 0000000000..cd865b611d --- /dev/null +++ b/TWEET.md @@ -0,0 +1,7 @@ +🆕 Release $version is out! Thanks to $contributor for the PR 👏 + +This release updates some of the internals to make the codebase more +maintainable and easier to work with. It also improves some of the +docstrings 📚👀 + +Get it here 👉 $release_url diff --git a/docs/breaking-changes.mdx b/docs/breaking-changes.mdx index f6028b8452..772c9ef8c5 100644 --- a/docs/breaking-changes.mdx +++ b/docs/breaking-changes.mdx @@ -4,6 +4,7 @@ title: List of breaking changes and deprecations # List of breaking changes and deprecations +- [Version 0.236.0 - 17 July 2024](./breaking-changes/0.236.0.md) - [Version 0.233.0 - 29 May 2024](./breaking-changes/0.233.0.md) - [Version 0.217.0 - 18 December 2023](./breaking-changes/0.217.0.md) - [Version 0.213.0 - 8 November 2023](./breaking-changes/0.213.0.md) diff --git a/docs/breaking-changes/0.236.0.mdx b/docs/breaking-changes/0.236.0.mdx new file mode 100644 index 0000000000..b2ed3a3216 --- /dev/null +++ b/docs/breaking-changes/0.236.0.mdx @@ -0,0 +1,19 @@ +--- +title: 0.236.0 Breaking Changes +slug: breaking-changes/0.236.0 +--- + +# v0.236.0 changes some of the imports + +This release changes the location of some files in the codebase, this is to make +the codebase more organized and easier to navigate. + +Technically most of these changes should not affect you, but if you were +importing some of the files directly you will need to update the imports. + +We created a codemod to help you with that, feel free to try and submit bugs if +we missed something. + +```bash +strawberry upgrade update-imports +``` diff --git a/docs/guides/field-extensions.mdx b/docs/guides/field-extensions.mdx index 645f859f7a..2921ceac39 100644 --- a/docs/guides/field-extensions.mdx +++ b/docs/guides/field-extensions.mdx @@ -79,7 +79,7 @@ import time import strawberry from strawberry.extensions import FieldExtension from strawberry.schema_directive import Location -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField @strawberry.schema_directive(locations=[Location.FIELD_DEFINITION]) diff --git a/poetry.lock b/poetry.lock index 17a5ce0bc5..579bd1fd23 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,14 +1,14 @@ -# This file is automatically @generated by Poetry 1.7.1 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. [[package]] name = "aiofiles" -version = "23.2.1" +version = "24.1.0" description = "File support for asyncio." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "aiofiles-23.2.1-py3-none-any.whl", hash = "sha256:19297512c647d4b27a2cf7c34caa7e405c0d60b5560618a29a9fe027b18b0107"}, - {file = "aiofiles-23.2.1.tar.gz", hash = "sha256:84ec2218d8419404abcb9f0c02df3f34c6e0a68ed41072acfb1cef5cbc29051a"}, + {file = "aiofiles-24.1.0-py3-none-any.whl", hash = "sha256:b4ec55f4195e3eb5d7abd1bf7e061763e864dd4954231fb8539a0ef8bb8260e5"}, + {file = "aiofiles-24.1.0.tar.gz", hash = "sha256:22a075c9e5a3810f0c2e48f3008c94d68c65d763b9b03857924c99e57355166c"}, ] [[package]] @@ -170,13 +170,13 @@ trio = ["trio (>=0.23)"] [[package]] name = "argcomplete" -version = "3.3.0" +version = "3.4.0" description = "Bash tab completion for argparse" optional = false python-versions = ">=3.8" files = [ - {file = "argcomplete-3.3.0-py3-none-any.whl", hash = "sha256:c168c3723482c031df3c207d4ba8fa702717ccb9fc0bfe4117166c1f537b4a54"}, - {file = "argcomplete-3.3.0.tar.gz", hash = "sha256:fd03ff4a5b9e6580569d34b273f741e85cd9e072f3feeeee3eba4891c70eda62"}, + {file = "argcomplete-3.4.0-py3-none-any.whl", hash = "sha256:69a79e083a716173e5532e0fa3bef45f793f4e61096cf52b5a42c0211c8b8aa5"}, + {file = "argcomplete-3.4.0.tar.gz", hash = "sha256:c2abcdfe1be8ace47ba777d4fce319eb13bf8ad9dace8d085dcad6eded88057f"}, ] [package.extras] @@ -411,13 +411,13 @@ files = [ [[package]] name = "botocore" -version = "1.34.113" +version = "1.34.144" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">=3.8" files = [ - {file = "botocore-1.34.113-py3-none-any.whl", hash = "sha256:8ca87776450ef41dd25c327eb6e504294230a5756940d68bcfdedc4a7cdeca97"}, - {file = "botocore-1.34.113.tar.gz", hash = "sha256:449912ba3c4ded64f21d09d428146dd9c05337b2a112e15511bf2c4888faae79"}, + {file = "botocore-1.34.144-py3-none-any.whl", hash = "sha256:a2cf26e1bf10d5917a2285e50257bc44e94a1d16574f282f3274f7a5d8d1f08b"}, + {file = "botocore-1.34.144.tar.gz", hash = "sha256:4215db28d25309d59c99507f1f77df9089e5bebbad35f6e19c7c44ec5383a3e8"}, ] [package.dependencies] @@ -429,7 +429,7 @@ urllib3 = [ ] [package.extras] -crt = ["awscrt (==0.20.9)"] +crt = ["awscrt (==0.20.11)"] [[package]] name = "build" @@ -518,13 +518,13 @@ ujson = ["ujson (>=5.7.0)"] [[package]] name = "certifi" -version = "2024.2.2" +version = "2024.7.4" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, - {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, + {file = "certifi-2024.7.4-py3-none-any.whl", hash = "sha256:c198e21b1289c2ab85ee4e67bb4b4ef3ead0892059901a8d5b622f24a1101e90"}, + {file = "certifi-2024.7.4.tar.gz", hash = "sha256:5a1e7645bc0ec61a09e26c36f6106dd4cf40c6db3a1fb6352b0244e7fb057c7b"}, ] [[package]] @@ -593,13 +593,13 @@ pycparser = "*" [[package]] name = "chalice" -version = "1.31.0" +version = "1.31.2" description = "Microframework" optional = false python-versions = "*" files = [ - {file = "chalice-1.31.0-py3-none-any.whl", hash = "sha256:f0680391f6bdc633869f91e14b1f0997bb0109152bdcbd7840033c41131ecb63"}, - {file = "chalice-1.31.0.tar.gz", hash = "sha256:4dbc03d6add40652c652bdf9df48047b7a9ac7518f1c2311a0498eeb8a774c91"}, + {file = "chalice-1.31.2-py3-none-any.whl", hash = "sha256:c076dc6bd73fa77b6d4d0a687e66f33eb2e26632b7208cd8164eb42df87c92f1"}, + {file = "chalice-1.31.2.tar.gz", hash = "sha256:57f3632b3fcb642e6a5932d8ee1d6975b3858f589306706881941e31828fb557"}, ] [package.dependencies] @@ -607,7 +607,7 @@ botocore = ">=1.14.0,<2.0.0" click = ">=7,<9.0" inquirer = ">=2.7.0,<3.0.0" jmespath = ">=0.9.3,<2.0.0" -pip = ">=9,<23.4" +pip = ">=9,<24.1" pyyaml = ">=5.3.1,<7.0.0" setuptools = "*" six = ">=1.10.0,<2.0.0" @@ -806,63 +806,63 @@ files = [ [[package]] name = "coverage" -version = "7.5.2" +version = "7.6.0" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:554c7327bf0fd688050348e22db7c8e163fb7219f3ecdd4732d7ed606b417263"}, - {file = "coverage-7.5.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d0305e02e40c7cfea5d08d6368576537a74c0eea62b77633179748d3519d6705"}, - {file = "coverage-7.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:829fb55ad437d757c70d5b1c51cfda9377f31506a0a3f3ac282bc6a387d6a5f1"}, - {file = "coverage-7.5.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:894b1acded706f1407a662d08e026bfd0ff1e59e9bd32062fea9d862564cfb65"}, - {file = "coverage-7.5.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe76d6dee5e4febefa83998b17926df3a04e5089e3d2b1688c74a9157798d7a2"}, - {file = "coverage-7.5.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:c7ebf2a37e4f5fea3c1a11e1f47cea7d75d0f2d8ef69635ddbd5c927083211fc"}, - {file = "coverage-7.5.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:20e611fc36e1a0fc7bbf957ef9c635c8807d71fbe5643e51b2769b3cc0fb0b51"}, - {file = "coverage-7.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7c5c5b7ae2763533152880d5b5b451acbc1089ade2336b710a24b2b0f5239d20"}, - {file = "coverage-7.5.2-cp310-cp310-win32.whl", hash = "sha256:1e4225990a87df898e40ca31c9e830c15c2c53b1d33df592bc8ef314d71f0281"}, - {file = "coverage-7.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:976cd92d9420e6e2aa6ce6a9d61f2b490e07cb468968adf371546b33b829284b"}, - {file = "coverage-7.5.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:5997d418c219dcd4dcba64e50671cca849aaf0dac3d7a2eeeb7d651a5bd735b8"}, - {file = "coverage-7.5.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ec27e93bbf5976f0465e8936f02eb5add99bbe4e4e7b233607e4d7622912d68d"}, - {file = "coverage-7.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1f11f98753800eb1ec872562a398081f6695f91cd01ce39819e36621003ec52a"}, - {file = "coverage-7.5.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6e34680049eecb30b6498784c9637c1c74277dcb1db75649a152f8004fbd6646"}, - {file = "coverage-7.5.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e12536446ad4527ac8ed91d8a607813085683bcce27af69e3b31cd72b3c5960"}, - {file = "coverage-7.5.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3d3f7744b8a8079d69af69d512e5abed4fb473057625588ce126088e50d05493"}, - {file = "coverage-7.5.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:431a3917e32223fcdb90b79fe60185864a9109631ebc05f6c5aa03781a00b513"}, - {file = "coverage-7.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a7c6574225f34ce45466f04751d957b5c5e6b69fca9351db017c9249786172ce"}, - {file = "coverage-7.5.2-cp311-cp311-win32.whl", hash = "sha256:2b144d142ec9987276aeff1326edbc0df8ba4afbd7232f0ca10ad57a115e95b6"}, - {file = "coverage-7.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:900532713115ac58bc3491b9d2b52704a05ed408ba0918d57fd72c94bc47fba1"}, - {file = "coverage-7.5.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:9a42970ce74c88bdf144df11c52c5cf4ad610d860de87c0883385a1c9d9fa4ab"}, - {file = "coverage-7.5.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:26716a1118c6ce2188283b4b60a898c3be29b480acbd0a91446ced4fe4e780d8"}, - {file = "coverage-7.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60b66b0363c5a2a79fba3d1cd7430c25bbd92c923d031cae906bdcb6e054d9a2"}, - {file = "coverage-7.5.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e5d22eba19273b2069e4efeff88c897a26bdc64633cbe0357a198f92dca94268"}, - {file = "coverage-7.5.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3bb5b92a0ab3d22dfdbfe845e2fef92717b067bdf41a5b68c7e3e857c0cff1a4"}, - {file = "coverage-7.5.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:1aef719b6559b521ae913ddeb38f5048c6d1a3d366865e8b320270b7bc4693c2"}, - {file = "coverage-7.5.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:8809c0ea0e8454f756e3bd5c36d04dddf222989216788a25bfd6724bfcee342c"}, - {file = "coverage-7.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:1acc2e2ef098a1d4bf535758085f508097316d738101a97c3f996bccba963ea5"}, - {file = "coverage-7.5.2-cp312-cp312-win32.whl", hash = "sha256:97de509043d3f0f2b2cd171bdccf408f175c7f7a99d36d566b1ae4dd84107985"}, - {file = "coverage-7.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:8941e35a0e991a7a20a1fa3e3182f82abe357211f2c335a9e6007067c3392fcf"}, - {file = "coverage-7.5.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:5662bf0f6fb6757f5c2d6279c541a5af55a39772c2362ed0920b27e3ce0e21f7"}, - {file = "coverage-7.5.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3d9c62cff2ffb4c2a95328488fd7aa96a7a4b34873150650fe76b19c08c9c792"}, - {file = "coverage-7.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74eeaa13e8200ad72fca9c5f37395fb310915cec6f1682b21375e84fd9770e84"}, - {file = "coverage-7.5.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f29bf497d51a5077994b265e976d78b09d9d0dff6ca5763dbb4804534a5d380"}, - {file = "coverage-7.5.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1f96aa94739593ae0707eda9813ce363a0a0374a810ae0eced383340fc4a1f73"}, - {file = "coverage-7.5.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:51b6cee539168a912b4b3b040e4042b9e2c9a7ad9c8546c09e4eaeff3eacba6b"}, - {file = "coverage-7.5.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:59a75e6aa5c25b50b5a1499f9718f2edff54257f545718c4fb100f48d570ead4"}, - {file = "coverage-7.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29da75ce20cb0a26d60e22658dd3230713c6c05a3465dd8ad040ffc991aea318"}, - {file = "coverage-7.5.2-cp38-cp38-win32.whl", hash = "sha256:23f2f16958b16152b43a39a5ecf4705757ddd284b3b17a77da3a62aef9c057ef"}, - {file = "coverage-7.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:9e41c94035e5cdb362beed681b58a707e8dc29ea446ea1713d92afeded9d1ddd"}, - {file = "coverage-7.5.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:06d96b9b19bbe7f049c2be3c4f9e06737ec6d8ef8933c7c3a4c557ef07936e46"}, - {file = "coverage-7.5.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:878243e1206828908a6b4a9ca7b1aa8bee9eb129bf7186fc381d2646f4524ce9"}, - {file = "coverage-7.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:482df956b055d3009d10fce81af6ffab28215d7ed6ad4a15e5c8e67cb7c5251c"}, - {file = "coverage-7.5.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a35c97af60a5492e9e89f8b7153fe24eadfd61cb3a2fb600df1a25b5dab34b7e"}, - {file = "coverage-7.5.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:24bb4c7859a3f757a116521d4d3a8a82befad56ea1bdacd17d6aafd113b0071e"}, - {file = "coverage-7.5.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:e1046aab24c48c694f0793f669ac49ea68acde6a0798ac5388abe0a5615b5ec8"}, - {file = "coverage-7.5.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:448ec61ea9ea7916d5579939362509145caaecf03161f6f13e366aebb692a631"}, - {file = "coverage-7.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4a00bd5ba8f1a4114720bef283cf31583d6cb1c510ce890a6da6c4268f0070b7"}, - {file = "coverage-7.5.2-cp39-cp39-win32.whl", hash = "sha256:9f805481d5eff2a96bac4da1570ef662bf970f9a16580dc2c169c8c3183fa02b"}, - {file = "coverage-7.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:2c79f058e7bec26b5295d53b8c39ecb623448c74ccc8378631f5cb5c16a7e02c"}, - {file = "coverage-7.5.2-pp38.pp39.pp310-none-any.whl", hash = "sha256:40dbb8e7727560fe8ab65efcddfec1ae25f30ef02e2f2e5d78cfb52a66781ec5"}, - {file = "coverage-7.5.2.tar.gz", hash = "sha256:13017a63b0e499c59b5ba94a8542fb62864ba3016127d1e4ef30d354fc2b00e9"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:dff044f661f59dace805eedb4a7404c573b6ff0cdba4a524141bc63d7be5c7fd"}, + {file = "coverage-7.6.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a8659fd33ee9e6ca03950cfdcdf271d645cf681609153f218826dd9805ab585c"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7792f0ab20df8071d669d929c75c97fecfa6bcab82c10ee4adb91c7a54055463"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d4b3cd1ca7cd73d229487fa5caca9e4bc1f0bca96526b922d61053ea751fe791"}, + {file = "coverage-7.6.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e7e128f85c0b419907d1f38e616c4f1e9f1d1b37a7949f44df9a73d5da5cd53c"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:a94925102c89247530ae1dab7dc02c690942566f22e189cbd53579b0693c0783"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:dcd070b5b585b50e6617e8972f3fbbee786afca71b1936ac06257f7e178f00f6"}, + {file = "coverage-7.6.0-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:d50a252b23b9b4dfeefc1f663c568a221092cbaded20a05a11665d0dbec9b8fb"}, + {file = "coverage-7.6.0-cp310-cp310-win32.whl", hash = "sha256:0e7b27d04131c46e6894f23a4ae186a6a2207209a05df5b6ad4caee6d54a222c"}, + {file = "coverage-7.6.0-cp310-cp310-win_amd64.whl", hash = "sha256:54dece71673b3187c86226c3ca793c5f891f9fc3d8aa183f2e3653da18566169"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c7b525ab52ce18c57ae232ba6f7010297a87ced82a2383b1afd238849c1ff933"}, + {file = "coverage-7.6.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4bea27c4269234e06f621f3fac3925f56ff34bc14521484b8f66a580aacc2e7d"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed8d1d1821ba5fc88d4a4f45387b65de52382fa3ef1f0115a4f7a20cdfab0e94"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:01c322ef2bbe15057bc4bf132b525b7e3f7206f071799eb8aa6ad1940bcf5fb1"}, + {file = "coverage-7.6.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:03cafe82c1b32b770a29fd6de923625ccac3185a54a5e66606da26d105f37dac"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0d1b923fc4a40c5832be4f35a5dab0e5ff89cddf83bb4174499e02ea089daf57"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:4b03741e70fb811d1a9a1d75355cf391f274ed85847f4b78e35459899f57af4d"}, + {file = "coverage-7.6.0-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:a73d18625f6a8a1cbb11eadc1d03929f9510f4131879288e3f7922097a429f63"}, + {file = "coverage-7.6.0-cp311-cp311-win32.whl", hash = "sha256:65fa405b837060db569a61ec368b74688f429b32fa47a8929a7a2f9b47183713"}, + {file = "coverage-7.6.0-cp311-cp311-win_amd64.whl", hash = "sha256:6379688fb4cfa921ae349c76eb1a9ab26b65f32b03d46bb0eed841fd4cb6afb1"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f7db0b6ae1f96ae41afe626095149ecd1b212b424626175a6633c2999eaad45b"}, + {file = "coverage-7.6.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:bbdf9a72403110a3bdae77948b8011f644571311c2fb35ee15f0f10a8fc082e8"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9cc44bf0315268e253bf563f3560e6c004efe38f76db03a1558274a6e04bf5d5"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:da8549d17489cd52f85a9829d0e1d91059359b3c54a26f28bec2c5d369524807"}, + {file = "coverage-7.6.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0086cd4fc71b7d485ac93ca4239c8f75732c2ae3ba83f6be1c9be59d9e2c6382"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1fad32ee9b27350687035cb5fdf9145bc9cf0a094a9577d43e909948ebcfa27b"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:044a0985a4f25b335882b0966625270a8d9db3d3409ddc49a4eb00b0ef5e8cee"}, + {file = "coverage-7.6.0-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:76d5f82213aa78098b9b964ea89de4617e70e0d43e97900c2778a50856dac605"}, + {file = "coverage-7.6.0-cp312-cp312-win32.whl", hash = "sha256:3c59105f8d58ce500f348c5b56163a4113a440dad6daa2294b5052a10db866da"}, + {file = "coverage-7.6.0-cp312-cp312-win_amd64.whl", hash = "sha256:ca5d79cfdae420a1d52bf177de4bc2289c321d6c961ae321503b2ca59c17ae67"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:d39bd10f0ae453554798b125d2f39884290c480f56e8a02ba7a6ed552005243b"}, + {file = "coverage-7.6.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:beb08e8508e53a568811016e59f3234d29c2583f6b6e28572f0954a6b4f7e03d"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b2e16f4cd2bc4d88ba30ca2d3bbf2f21f00f382cf4e1ce3b1ddc96c634bc48ca"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6616d1c9bf1e3faea78711ee42a8b972367d82ceae233ec0ac61cc7fec09fa6b"}, + {file = "coverage-7.6.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ad4567d6c334c46046d1c4c20024de2a1c3abc626817ae21ae3da600f5779b44"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:d17c6a415d68cfe1091d3296ba5749d3d8696e42c37fca5d4860c5bf7b729f03"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:9146579352d7b5f6412735d0f203bbd8d00113a680b66565e205bc605ef81bc6"}, + {file = "coverage-7.6.0-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:cdab02a0a941af190df8782aafc591ef3ad08824f97850b015c8c6a8b3877b0b"}, + {file = "coverage-7.6.0-cp38-cp38-win32.whl", hash = "sha256:df423f351b162a702c053d5dddc0fc0ef9a9e27ea3f449781ace5f906b664428"}, + {file = "coverage-7.6.0-cp38-cp38-win_amd64.whl", hash = "sha256:f2501d60d7497fd55e391f423f965bbe9e650e9ffc3c627d5f0ac516026000b8"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7221f9ac9dad9492cecab6f676b3eaf9185141539d5c9689d13fd6b0d7de840c"}, + {file = "coverage-7.6.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ddaaa91bfc4477d2871442bbf30a125e8fe6b05da8a0015507bfbf4718228ab2"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4cbe651f3904e28f3a55d6f371203049034b4ddbce65a54527a3f189ca3b390"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:831b476d79408ab6ccfadaaf199906c833f02fdb32c9ab907b1d4aa0713cfa3b"}, + {file = "coverage-7.6.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:46c3d091059ad0b9c59d1034de74a7f36dcfa7f6d3bde782c49deb42438f2450"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:4d5fae0a22dc86259dee66f2cc6c1d3e490c4a1214d7daa2a93d07491c5c04b6"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:07ed352205574aad067482e53dd606926afebcb5590653121063fbf4e2175166"}, + {file = "coverage-7.6.0-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:49c76cdfa13015c4560702574bad67f0e15ca5a2872c6a125f6327ead2b731dd"}, + {file = "coverage-7.6.0-cp39-cp39-win32.whl", hash = "sha256:482855914928c8175735a2a59c8dc5806cf7d8f032e4820d52e845d1f731dca2"}, + {file = "coverage-7.6.0-cp39-cp39-win_amd64.whl", hash = "sha256:543ef9179bc55edfd895154a51792b01c017c87af0ebaae092720152e19e42ca"}, + {file = "coverage-7.6.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:6fe885135c8a479d3e37a7aae61cbd3a0fb2deccb4dda3c25f92a49189f766d6"}, + {file = "coverage-7.6.0.tar.gz", hash = "sha256:289cc803fa1dc901f84701ac10c9ee873619320f2f9aff38794db4a4a0268d51"}, ] [package.dependencies] @@ -884,43 +884,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.7" +version = "42.0.8" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:a987f840718078212fdf4504d0fd4c6effe34a7e4740378e59d47696e8dfb477"}, - {file = "cryptography-42.0.7-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:bd13b5e9b543532453de08bcdc3cc7cebec6f9883e886fd20a92f26940fd3e7a"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a79165431551042cc9d1d90e6145d5d0d3ab0f2d66326c201d9b0e7f5bf43604"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a47787a5e3649008a1102d3df55424e86606c9bae6fb77ac59afe06d234605f8"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:02c0eee2d7133bdbbc5e24441258d5d2244beb31da5ed19fbb80315f4bbbff55"}, - {file = "cryptography-42.0.7-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5e44507bf8d14b36b8389b226665d597bc0f18ea035d75b4e53c7b1ea84583cc"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:7f8b25fa616d8b846aef64b15c606bb0828dbc35faf90566eb139aa9cff67af2"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:93a3209f6bb2b33e725ed08ee0991b92976dfdcf4e8b38646540674fc7508e13"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:e6b8f1881dac458c34778d0a424ae5769de30544fc678eac51c1c8bb2183e9da"}, - {file = "cryptography-42.0.7-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:3de9a45d3b2b7d8088c3fbf1ed4395dfeff79d07842217b38df14ef09ce1d8d7"}, - {file = "cryptography-42.0.7-cp37-abi3-win32.whl", hash = "sha256:789caea816c6704f63f6241a519bfa347f72fbd67ba28d04636b7c6b7da94b0b"}, - {file = "cryptography-42.0.7-cp37-abi3-win_amd64.whl", hash = "sha256:8cb8ce7c3347fcf9446f201dc30e2d5a3c898d009126010cbd1f443f28b52678"}, - {file = "cryptography-42.0.7-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:a3a5ac8b56fe37f3125e5b72b61dcde43283e5370827f5233893d461b7360cd4"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:779245e13b9a6638df14641d029add5dc17edbef6ec915688f3acb9e720a5858"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0d563795db98b4cd57742a78a288cdbdc9daedac29f2239793071fe114f13785"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:31adb7d06fe4383226c3e963471f6837742889b3c4caa55aac20ad951bc8ffda"}, - {file = "cryptography-42.0.7-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:efd0bf5205240182e0f13bcaea41be4fdf5c22c5129fc7ced4a0282ac86998c9"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:a9bc127cdc4ecf87a5ea22a2556cab6c7eda2923f84e4f3cc588e8470ce4e42e"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:3577d029bc3f4827dd5bf8bf7710cac13527b470bbf1820a3f394adb38ed7d5f"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2e47577f9b18723fa294b0ea9a17d5e53a227867a0a4904a1a076d1646d45ca1"}, - {file = "cryptography-42.0.7-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:1a58839984d9cb34c855197043eaae2c187d930ca6d644612843b4fe8513c886"}, - {file = "cryptography-42.0.7-cp39-abi3-win32.whl", hash = "sha256:e6b79d0adb01aae87e8a44c2b64bc3f3fe59515280e00fb6d57a7267a2583cda"}, - {file = "cryptography-42.0.7-cp39-abi3-win_amd64.whl", hash = "sha256:16268d46086bb8ad5bf0a2b5544d8a9ed87a0e33f5e77dd3c3301e63d941a83b"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:2954fccea107026512b15afb4aa664a5640cd0af630e2ee3962f2602693f0c82"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:362e7197754c231797ec45ee081f3088a27a47c6c01eff2ac83f60f85a50fe60"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4f698edacf9c9e0371112792558d2f705b5645076cc0aaae02f816a0171770fd"}, - {file = "cryptography-42.0.7-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:5482e789294854c28237bba77c4c83be698be740e31a3ae5e879ee5444166582"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:e9b2a6309f14c0497f348d08a065d52f3020656f675819fc405fb63bbcd26562"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:d8e3098721b84392ee45af2dd554c947c32cc52f862b6a3ae982dbb90f577f14"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c65f96dad14f8528a447414125e1fc8feb2ad5a272b8f68477abbcc1ea7d94b9"}, - {file = "cryptography-42.0.7-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:36017400817987670037fbb0324d71489b6ead6231c9604f8fc1f7d008087c68"}, - {file = "cryptography-42.0.7.tar.gz", hash = "sha256:ecbfbc00bf55888edda9868a4cf927205de8499e7fabe6c050322298382953f2"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:81d8a521705787afe7a18d5bfb47ea9d9cc068206270aad0b96a725022e18d2e"}, + {file = "cryptography-42.0.8-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:961e61cefdcb06e0c6d7e3a1b22ebe8b996eb2bf50614e89384be54c48c6b63d"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e3ec3672626e1b9e55afd0df6d774ff0e953452886e06e0f1eb7eb0c832e8902"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e599b53fd95357d92304510fb7bda8523ed1f79ca98dce2f43c115950aa78801"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:5226d5d21ab681f432a9c1cf8b658c0cb02533eece706b155e5fbd8a0cdd3949"}, + {file = "cryptography-42.0.8-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:6b7c4f03ce01afd3b76cf69a5455caa9cfa3de8c8f493e0d3ab7d20611c8dae9"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:2346b911eb349ab547076f47f2e035fc8ff2c02380a7cbbf8d87114fa0f1c583"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad803773e9df0b92e0a817d22fd8a3675493f690b96130a5e24f1b8fabbea9c7"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:2f66d9cd9147ee495a8374a45ca445819f8929a3efcd2e3df6428e46c3cbb10b"}, + {file = "cryptography-42.0.8-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:d45b940883a03e19e944456a558b67a41160e367a719833c53de6911cabba2b7"}, + {file = "cryptography-42.0.8-cp37-abi3-win32.whl", hash = "sha256:a0c5b2b0585b6af82d7e385f55a8bc568abff8923af147ee3c07bd8b42cda8b2"}, + {file = "cryptography-42.0.8-cp37-abi3-win_amd64.whl", hash = "sha256:57080dee41209e556a9a4ce60d229244f7a66ef52750f813bfbe18959770cfba"}, + {file = "cryptography-42.0.8-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:dea567d1b0e8bc5764b9443858b673b734100c2871dc93163f58c46a97a83d28"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c4783183f7cb757b73b2ae9aed6599b96338eb957233c58ca8f49a49cc32fd5e"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a0608251135d0e03111152e41f0cc2392d1e74e35703960d4190b2e0f4ca9c70"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:dc0fdf6787f37b1c6b08e6dfc892d9d068b5bdb671198c72072828b80bd5fe4c"}, + {file = "cryptography-42.0.8-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:9c0c1716c8447ee7dbf08d6db2e5c41c688544c61074b54fc4564196f55c25a7"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:fff12c88a672ab9c9c1cf7b0c80e3ad9e2ebd9d828d955c126be4fd3e5578c9e"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:cafb92b2bc622cd1aa6a1dce4b93307792633f4c5fe1f46c6b97cf67073ec961"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:31f721658a29331f895a5a54e7e82075554ccfb8b163a18719d342f5ffe5ecb1"}, + {file = "cryptography-42.0.8-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:b297f90c5723d04bcc8265fc2a0f86d4ea2e0f7ab4b6994459548d3a6b992a14"}, + {file = "cryptography-42.0.8-cp39-abi3-win32.whl", hash = "sha256:2f88d197e66c65be5e42cd72e5c18afbfae3f741742070e3019ac8f4ac57262c"}, + {file = "cryptography-42.0.8-cp39-abi3-win_amd64.whl", hash = "sha256:fa76fbb7596cc5839320000cdd5d0955313696d9511debab7ee7278fc8b5c84a"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:ba4f0a211697362e89ad822e667d8d340b4d8d55fae72cdd619389fb5912eefe"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:81884c4d096c272f00aeb1f11cf62ccd39763581645b0812e99a91505fa48e0c"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:c9bb2ae11bfbab395bdd072985abde58ea9860ed84e59dbc0463a5d0159f5b71"}, + {file = "cryptography-42.0.8-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:7016f837e15b0a1c119d27ecd89b3515f01f90a8615ed5e9427e30d9cdbfed3d"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5a94eccb2a81a309806027e1670a358b99b8fe8bfe9f8d329f27d72c094dde8c"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:dec9b018df185f08483f294cae6ccac29e7a6e0678996587363dc352dc65c842"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:343728aac38decfdeecf55ecab3264b015be68fc2816ca800db649607aeee648"}, + {file = "cryptography-42.0.8-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:013629ae70b40af70c9a7a5db40abe5d9054e6f4380e50ce769947b73bf3caad"}, + {file = "cryptography-42.0.8.tar.gz", hash = "sha256:8d09d05439ce7baa8e9e95b07ec5b6c886f548deb7e0f69ef25f64b3bce842f2"}, ] [package.dependencies] @@ -974,71 +974,71 @@ serialization = ["protobuf (>=3.0.0)"] [[package]] name = "ddtrace" -version = "2.8.5" +version = "2.9.2" description = "Datadog APM client library" optional = false python-versions = ">=3.7" files = [ - {file = "ddtrace-2.8.5-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:9df3b59794352d3af6df52278e724999dc3b70e7cf59142e3c6170dd43715a6c"}, - {file = "ddtrace-2.8.5-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:7dca42e52f74416b1085664dc3412be01cc27e50218cb8e7f9c46473fdecdb2d"}, - {file = "ddtrace-2.8.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:32b5c067e1a907202f25e6376d9e676644edcf16cae7beb9ac1087a067833393"}, - {file = "ddtrace-2.8.5-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c58d3e106af514486f65f09fee75a42a3fd83d5be9538befd5d5ceda6995da3b"}, - {file = "ddtrace-2.8.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1247855a6465c2fc167977d6bd8497c8b28e177530a12faad16fd4f3c31a4dac"}, - {file = "ddtrace-2.8.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e03aefcca84e57babf9e74f5ed859b249826eb3213edd5d6e4003c702dbbcd68"}, - {file = "ddtrace-2.8.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a6f2cf37088a5e528d1f78d571cec30f9b1cc03cf1097bf609f7f7c13a3aada8"}, - {file = "ddtrace-2.8.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0ecc3d65adeac43e2ec3f9e4e9ce2a166230a7c7f6e5913d9b80753983a414f1"}, - {file = "ddtrace-2.8.5-cp310-cp310-win32.whl", hash = "sha256:7be8dfa8104bc95a06b484bf8d04374e6f081c2158b6718fa0a955813fd530ec"}, - {file = "ddtrace-2.8.5-cp310-cp310-win_amd64.whl", hash = "sha256:adcb83109ac918e233c3c3d825a3bbc82c8fd1e45d632466bd15a21122ed2b81"}, - {file = "ddtrace-2.8.5-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:da94a1752032ab805bccb4878fdda671719f13c541cfca004aedd9b99c92ccfd"}, - {file = "ddtrace-2.8.5-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:f15d799e3e7c3055cdb8e4b4bdf5f9c137893e0e04ff6b430d0f663bb48dd176"}, - {file = "ddtrace-2.8.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:376ac38cd9de471842a5b395005deed1d7ca7448b7dd66402bf108598c996e0d"}, - {file = "ddtrace-2.8.5-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:77be9629d7123636a7559bf49bc3a9255febcea22685214c441ace28d3bf1e6b"}, - {file = "ddtrace-2.8.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b92b8e0dab9444a79c7afa4253e88e1948ac51267deb354251fb2ee64c0659f1"}, - {file = "ddtrace-2.8.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:33c5a3e7c3fe82be8316b7264bca45627cc105c9b8f72eef6b6cf9dea6102ca1"}, - {file = "ddtrace-2.8.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:521c0d6c972d51a887415cccf6c8ad49761fc7ce7af4f70794648429c9aa6ea8"}, - {file = "ddtrace-2.8.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7360f43edec29f5ded3b9f3eb3b549997fb84484b9f3f33bb97a37dfd13266a0"}, - {file = "ddtrace-2.8.5-cp311-cp311-win32.whl", hash = "sha256:b40194643b21159910bd52f041597aee8d594d5450feb16ffb1ac0bd51016eb7"}, - {file = "ddtrace-2.8.5-cp311-cp311-win_amd64.whl", hash = "sha256:6c45f818c08eab1c6898ea8263422cf19e2425bf725e1843c094c5628baac589"}, - {file = "ddtrace-2.8.5-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:0cb3bc95ca4dae45531ad59d859712ccd52a465f19b0e03d3703e1c9fcec8614"}, - {file = "ddtrace-2.8.5-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:51ef36d884cb508166c3699ec8fd01ac32749bea2e826953e697658697e351f4"}, - {file = "ddtrace-2.8.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c3af5070b6eda559555c68a92bdef2d8495208fff0a123601655ebc6a0ec6d02"}, - {file = "ddtrace-2.8.5-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7b7eb223d7c000daa69d7d82e36af254f8e49e154b4713d842b60b2d4cbc250c"}, - {file = "ddtrace-2.8.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c16a77926332615c018c44591c93215b08aaddfd724bd84bfbee4efa8bfcf877"}, - {file = "ddtrace-2.8.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bf61abef38d26e4e892fdf63493541290630038d78f8294dde81596ed7208858"}, - {file = "ddtrace-2.8.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:5ddebfcef09e84b9c6efa58036576347243946473a6db4f143f4b60d9f5e6b34"}, - {file = "ddtrace-2.8.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:901d47e455cb197ee12604a10b5d10ee74e0b56a5e0a50092e19a654976923dc"}, - {file = "ddtrace-2.8.5-cp312-cp312-win32.whl", hash = "sha256:9ec3c24d1a7ea7e1ac5c8251d074b7c053e60f3060f335fb88e612fe35dbbe54"}, - {file = "ddtrace-2.8.5-cp312-cp312-win_amd64.whl", hash = "sha256:9430e3197f4e56cce4a2b0829faddf4c4efde6588fea66fb4aa3adc4946cae0c"}, - {file = "ddtrace-2.8.5-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:3a1d029713e6fa6887c4fb3e51e1a75c39855270edafce2dbb8678d168d3272a"}, - {file = "ddtrace-2.8.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:edc2c7cc433659069e56bf064560a348aad485b53799a5870b7e0d488a83cc1d"}, - {file = "ddtrace-2.8.5-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f06b1377d45f4664148fddec54180cd888f5abdb41fc31942641cd7797f17848"}, - {file = "ddtrace-2.8.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5b6ceae3201c77b08801f55a751cf0f1b85d250cfac6dfd4a9f0663c131a916d"}, - {file = "ddtrace-2.8.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:a6f67d1c9dec80469921424272a83b5cad57e4b26ae750fec4b763f1bf6c4ece"}, - {file = "ddtrace-2.8.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:2c08eb99996e79708948d7eb547c02888daa64a7f2e220ba8ff6144e63996a8c"}, - {file = "ddtrace-2.8.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:dac2370ea09f61530f01df454394f8c291a77a08d7c73180b1b5743746e6a390"}, - {file = "ddtrace-2.8.5-cp37-cp37m-win32.whl", hash = "sha256:9b5cfb81984c74a60cdb3c167203a4bbeaa319b5242e17b5ca0adbee4df54a7f"}, - {file = "ddtrace-2.8.5-cp37-cp37m-win_amd64.whl", hash = "sha256:0674abd6118382f82c7139bab7de106644b260f09ec43f56952ae36b9840f191"}, - {file = "ddtrace-2.8.5-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:1312acce7049d72a7e63110525b30c1bca192cf8dbffbca5fc626e6268a850ec"}, - {file = "ddtrace-2.8.5-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:1bcedeca9c60e6eb9dfb3654bdce383161322b1261ab6d1cf067f43451cf81c5"}, - {file = "ddtrace-2.8.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:b8630a7cc4d037f0ff214f9b65093b0482f3e0efd28043690ac003cbfd9ac56d"}, - {file = "ddtrace-2.8.5-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:88dd0f886fd02c215f6017460a088695b55d945c61171c2e7897728572ca2616"}, - {file = "ddtrace-2.8.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2379716ec9ddc0c8f38c48a0b19e2116c167eb0de34436a48d348351dde60dbe"}, - {file = "ddtrace-2.8.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8152cb0a87ed63177c0ee2a51a5d43dfe7663e398c86d7c46129a02c21456c9c"}, - {file = "ddtrace-2.8.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:982adfd87ed1d45e8f98b6ac37be0e4a6d09f8fa550d6f3c0ee2bd8d270cf55f"}, - {file = "ddtrace-2.8.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:9e430bcc2c806d6dd249ec5281c38c2507d58ca903d56df1cac171fac4bd082a"}, - {file = "ddtrace-2.8.5-cp38-cp38-win32.whl", hash = "sha256:7f77edf558f3548c55cacca1402ee85a371f2522423f54e1e92a880933fbaaf6"}, - {file = "ddtrace-2.8.5-cp38-cp38-win_amd64.whl", hash = "sha256:f992a657bc0b12dee142c43256733500dcb5d1d5667e8282667875edce10e055"}, - {file = "ddtrace-2.8.5-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:6429395c9f380ff668d8ec4914a3eea095bfa8cc243b07939fbf5d3a3c68e919"}, - {file = "ddtrace-2.8.5-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:f46a66d324a0b42e6fd1ba7a9c703ff7fc4e9e00e08f3c283d2e54e24a8e63c2"}, - {file = "ddtrace-2.8.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e0cd1b698a258afad559344dbe703ed35032558298d024d9fa4c83466dd21892"}, - {file = "ddtrace-2.8.5-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5893d1b9b5ae0cca73977ad5056abaf7afb9bcd4e8c92d6abbe6208925a29027"}, - {file = "ddtrace-2.8.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a780f6277c414bc8f004937c0d293b682036905de31aa2edbdf89eaecf1a1d4"}, - {file = "ddtrace-2.8.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e8b797f34a7475f57f251d6f6c53b5c72d6964351e1c1b147efc55844153697"}, - {file = "ddtrace-2.8.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:afd4a0c0c377d4ee99cff78e4d73727850b49434bd2042743468a3244757939c"}, - {file = "ddtrace-2.8.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1731aa5685161118696a439891bedb31a9c6bfa3233acca076dbed3f3caf239e"}, - {file = "ddtrace-2.8.5-cp39-cp39-win32.whl", hash = "sha256:d2987a57da49557a084d8c5512f3632058d7eeee8e32e49fc5e12c821963cf88"}, - {file = "ddtrace-2.8.5-cp39-cp39-win_amd64.whl", hash = "sha256:0c7f9506fc33448a91d706ee838b712ac76a00dc2213c96ddc62e25ce1a3708e"}, - {file = "ddtrace-2.8.5.tar.gz", hash = "sha256:11e055acbc9de6d0d2fa26d9ca97a0256ede9ff36199419bce23837764c84559"}, + {file = "ddtrace-2.9.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:aaa4c4c0d001e5695d8d8f03361e25fbba62716bd4dbc861daa45bc71802a165"}, + {file = "ddtrace-2.9.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:99fa4f3437dd908622d015fd0a92015eb2bb718554fd6e9cb3c8984737ca8173"}, + {file = "ddtrace-2.9.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6c3be4f5ea1378138f26b6a84b23048a681e705e602f5f4a2db6c9f1ae6f52c9"}, + {file = "ddtrace-2.9.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b79f44ebd64496e8d2c85250290486f08cf338b02cb484a24d17204d11af39d6"}, + {file = "ddtrace-2.9.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0f9bcf9dc2fee145c1fa295e451898dd0b6fbdbdd7cc205b5c226c945369238"}, + {file = "ddtrace-2.9.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6418399be4eb0100d8c25e7154d94032dafb08f3387864db6ea64ae6b01044a4"}, + {file = "ddtrace-2.9.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:72a3d3cdca7508b787e6bd0d09a75f1cb7cba9580f91591be51af22c9d9bf9bf"}, + {file = "ddtrace-2.9.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:93efef2f0b88792fefe5840c47c9f262fc94471078c0cf10f54831b44ea422b6"}, + {file = "ddtrace-2.9.2-cp310-cp310-win32.whl", hash = "sha256:5ad725a61da4b4d76368b7e205ae327ae39cab5ec64d8c6e16760bc86d6a6507"}, + {file = "ddtrace-2.9.2-cp310-cp310-win_amd64.whl", hash = "sha256:9a31c9a2d714b3d45fb5ae24b912521d4569d1dac3fd3fc3c77ec9fcba5dfd26"}, + {file = "ddtrace-2.9.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:358ccb1b7bf9ec39658e00aa1ba4972712603deefb5562219ce0ccc5e7521e52"}, + {file = "ddtrace-2.9.2-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:98b44e28151b07a9ce8ae27951978ac340f66640c833dee9b396831ddf06a9a6"}, + {file = "ddtrace-2.9.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c9d409e6d061bbe3d026696403edd37b390a4a8bc661b7490c02199a8a9da7e9"}, + {file = "ddtrace-2.9.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6a26ecdf3f7666e604bb15e20d32b63d948e85bcde6c63b2f1d45af0681079bf"}, + {file = "ddtrace-2.9.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:519e2a9e6daf592bf4a9993ae782621016770b5182ed7567fba0ef23812ca6d7"}, + {file = "ddtrace-2.9.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:2243582de6aef14fc87621169d586679572cf3f39c79cef6f898963f37a6a296"}, + {file = "ddtrace-2.9.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c176c0ea15e2b94f139ca68ba3d5ee48430c717ae785cd9e51eeb59634629c94"}, + {file = "ddtrace-2.9.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e9befe7b40141a686f991fd98780b9dfe31e55b9ed3cf685a5fcfa256789b879"}, + {file = "ddtrace-2.9.2-cp311-cp311-win32.whl", hash = "sha256:84f1a7b517f1790374ad1079e783cd893634518521ae6e2ed41a4e343227830b"}, + {file = "ddtrace-2.9.2-cp311-cp311-win_amd64.whl", hash = "sha256:4c34823c3ed3e1da5fe11de483c4091179f21fb4f255144a5082af2f52a1e02e"}, + {file = "ddtrace-2.9.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b5b749b609036917cab6ae9187aaf4e83051e0396bd0d4d9f2af4bfbaf866bf2"}, + {file = "ddtrace-2.9.2-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:b1f21076ecb3a7736e92dc288ff6437337098f9acc6dcbbebfcfb7a1ce7aabff"}, + {file = "ddtrace-2.9.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8bb857a7a66ac56d041f2e40778f88cea51db55d0611beb36b6a45b52504c90d"}, + {file = "ddtrace-2.9.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f1f7e403b77f6c26d2f813712c38cda09d4b5c2e07e5e6e578eb71ce674382ce"}, + {file = "ddtrace-2.9.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dace336a9c14f6f8953732806d4fccee489d670aac6b2b75a3fa9eb94c32fda6"}, + {file = "ddtrace-2.9.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:e7c59ce06f887db4a6a0309bdc504beada8969979876dc8f54681e10d1993426"}, + {file = "ddtrace-2.9.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0b7c81323a952da21e7a85b20334bb33ba47600c7b7604f4267022217c7025e3"}, + {file = "ddtrace-2.9.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:07aa83c4a6e6822fd365a92f972576980badc3d426d257d9814212d0a2a5f837"}, + {file = "ddtrace-2.9.2-cp312-cp312-win32.whl", hash = "sha256:5fe686fe657b9871f6faf2f7f7e97e659421c17dc5903b43ff174f8866726a21"}, + {file = "ddtrace-2.9.2-cp312-cp312-win_amd64.whl", hash = "sha256:858b61e57cb11c5c467907add391ce8ad2dec823bc326c8e1505368c4f0ac7d4"}, + {file = "ddtrace-2.9.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:28ee6dee988609f1d720934d52f6a29b7c9b914a39fb70528a51a194d1ab3b8d"}, + {file = "ddtrace-2.9.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07ade55550c3b1debb96f9ffdb716eae5bd48335d3ca54e9c5b9e492a7dc91f2"}, + {file = "ddtrace-2.9.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:41cf398da7a28a78c108cccfc87abe33d7e8936f99462f6fee3877fb180913c0"}, + {file = "ddtrace-2.9.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2d79259e140070dc2533c3bc5776df7731baa9e2f078daf4ce708efd33ac00d3"}, + {file = "ddtrace-2.9.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:753f845308d97f8290d4ff7ce92e7875b83efa4eb5ff3fac8e2042caf6761bfb"}, + {file = "ddtrace-2.9.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:28c88f5efc946dddefc320c682c93bb65001ee38e78569e496b20823f21ef745"}, + {file = "ddtrace-2.9.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:765d7c031b54da32fc18cbeafadd3c22cd1a6f98317e6e0498bf2898fbeae350"}, + {file = "ddtrace-2.9.2-cp37-cp37m-win32.whl", hash = "sha256:7b5dddfbd23646a16ad9b991fd2866628dc56b7abe8dd7100962ce0681b738c9"}, + {file = "ddtrace-2.9.2-cp37-cp37m-win_amd64.whl", hash = "sha256:c8c17f5f57f65ea95d6bf61511869abfaa10fb555e81b0294e30226afa047115"}, + {file = "ddtrace-2.9.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:aa329ace4909bd402de3d9dbaaaff9e3545fd5a9fad1c72a39e075743c673099"}, + {file = "ddtrace-2.9.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:afebe7e5467a743795a878cad3e9658f704c5572ca398a70a840da034a571f67"}, + {file = "ddtrace-2.9.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bd1271c597f088b1ff7e5881138a1317a799025c834bd496cecfdcb816748e51"}, + {file = "ddtrace-2.9.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:24da863c984d3261c7dae9362cf48c01fc0dc1557c92de336a1bbeb08452e046"}, + {file = "ddtrace-2.9.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e68014fa46b4be6e58cc64feb3516ec856df714ce3d4576f3d6df9079ddfba8f"}, + {file = "ddtrace-2.9.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10824581a708c643515747e814c6b146bed6d91e687a825111858a198eee75e6"}, + {file = "ddtrace-2.9.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:03c6874475db7d7b1fb563cd6aa3ba0c22ee72bb8c6cceb36c84dba6ca21e2f4"}, + {file = "ddtrace-2.9.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b91b8cfc7239317fe6b185beb0b8153769b43bf11fb2cda9e6e2996962e4b820"}, + {file = "ddtrace-2.9.2-cp38-cp38-win32.whl", hash = "sha256:0d9456defb679d6225d32967902853cd4d8b01f55e4da18089a9ffa9d6495328"}, + {file = "ddtrace-2.9.2-cp38-cp38-win_amd64.whl", hash = "sha256:d39c2da38c295aba1810083ce63d37041e3e40a06add960f6edf5a33517f743c"}, + {file = "ddtrace-2.9.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:c251e684c9e3a7828308a74d2be073d88cf28b4be457a5c201a2755ef9205d24"}, + {file = "ddtrace-2.9.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:707151d2aa4f04388af4e3e8b0783e99b110fa0f2f1db775f64667c62bd249c2"}, + {file = "ddtrace-2.9.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c536a53d628e8d96812edea10d84e9df2f9022a7e932beb10e187c98f4471ec"}, + {file = "ddtrace-2.9.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9c093fbabdeb6ecc6a749b1b5f80ebe557dcf768984bb42aadf66c57f04f3b85"}, + {file = "ddtrace-2.9.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4d5b6c58d4ebc988f61a5f81e8953531ee59490240d69463592ff63dd2f6e00b"}, + {file = "ddtrace-2.9.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:85511fade95b21ca29e9ba314eeb5847733a81128d8cbdbc43012caba45c03c8"}, + {file = "ddtrace-2.9.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8b3b2f64414c57742e7be924079e80576110abf8725f70e56bce0603877d08bf"}, + {file = "ddtrace-2.9.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ad04028487d7cdb44318323ab4438c873e01855c3391a3c47a4400ff499bcbfc"}, + {file = "ddtrace-2.9.2-cp39-cp39-win32.whl", hash = "sha256:206759c2847ee7174e14c4a2cffd3086ad55aca10d73f50b24cc2e00ec22e871"}, + {file = "ddtrace-2.9.2-cp39-cp39-win_amd64.whl", hash = "sha256:d916dbfeeebb38cd48c64c771b74276b716902471f6bf9c02e8d5c278f0baad1"}, + {file = "ddtrace-2.9.2.tar.gz", hash = "sha256:40775def3f3fc01d1c4c5eec64f7f624621eb394fe62d107c27e181123443716"}, ] [package.dependencies] @@ -1055,7 +1055,6 @@ opentelemetry-api = ">=1" protobuf = ">=3" setuptools = {version = "*", markers = "python_version >= \"3.12\""} six = ">=1.12.0" -sqlparse = ">=0.2.2" typing-extensions = "*" xmltodict = ">=0.12" @@ -1093,13 +1092,13 @@ files = [ [[package]] name = "django" -version = "4.2.13" +version = "4.2.14" description = "A high-level Python web framework that encourages rapid development and clean, pragmatic design." optional = false python-versions = ">=3.8" files = [ - {file = "Django-4.2.13-py3-none-any.whl", hash = "sha256:a17fcba2aad3fc7d46fdb23215095dbbd64e6174bf4589171e732b18b07e426a"}, - {file = "Django-4.2.13.tar.gz", hash = "sha256:837e3cf1f6c31347a1396a3f6b65688f2b4bb4a11c580dcb628b5afe527b68a5"}, + {file = "Django-4.2.14-py3-none-any.whl", hash = "sha256:3ec32bc2c616ab02834b9cac93143a7dc1cdcd5b822d78ac95fc20a38c534240"}, + {file = "Django-4.2.14.tar.gz", hash = "sha256:fc6919875a6226c7ffcae1a7d51e0f2ceaf6f160393180818f6c95f51b1e7b96"}, ] [package.dependencies] @@ -1221,13 +1220,13 @@ pgp = ["gpg"] [[package]] name = "email-validator" -version = "2.1.1" +version = "2.2.0" description = "A robust email address syntax and deliverability validation library." optional = false python-versions = ">=3.8" files = [ - {file = "email_validator-2.1.1-py3-none-any.whl", hash = "sha256:97d882d174e2a65732fb43bfce81a3a834cbc1bde8bf419e30ef5ea976370a05"}, - {file = "email_validator-2.1.1.tar.gz", hash = "sha256:200a70680ba08904be6d1eef729205cc0d687634399a5924d842533efb824b84"}, + {file = "email_validator-2.2.0-py3-none-any.whl", hash = "sha256:561977c2d73ce3611850a06fa56b414621e0c8faa9d66f2611407d87465da631"}, + {file = "email_validator-2.2.0.tar.gz", hash = "sha256:cb690f344c617a714f22e66ae771445a1ceb46821152df8e165c5f9a364582b7"}, ] [package.dependencies] @@ -1236,13 +1235,13 @@ idna = ">=2.0.0" [[package]] name = "envier" -version = "0.5.1" +version = "0.5.2" description = "Python application configuration via the environment" optional = false python-versions = ">=3.7" files = [ - {file = "envier-0.5.1-py3-none-any.whl", hash = "sha256:b45ef6051fea33d0c32a64e186bff2cfb446e2242d6781216c9bc9ce708c5909"}, - {file = "envier-0.5.1.tar.gz", hash = "sha256:bd5ccf707447973ea0f4125b7df202ba415ad888bcdcb8df80e0b002ee11ffdb"}, + {file = "envier-0.5.2-py3-none-any.whl", hash = "sha256:65099cf3aa9b3b3b4b92db2f7d29e2910672e085b76f7e587d2167561a834add"}, + {file = "envier-0.5.2.tar.gz", hash = "sha256:4e7e398cb09a8dd360508ef7e12511a152355426d2544b8487a34dad27cc20ad"}, ] [package.extras] @@ -1250,13 +1249,13 @@ mypy = ["mypy"] [[package]] name = "exceptiongroup" -version = "1.2.1" +version = "1.2.2" description = "Backport of PEP 654 (exception groups)" optional = false python-versions = ">=3.7" files = [ - {file = "exceptiongroup-1.2.1-py3-none-any.whl", hash = "sha256:5258b9ed329c5bbdd31a309f53cbfb0b155341807f6ff7606a1e801a891b29ad"}, - {file = "exceptiongroup-1.2.1.tar.gz", hash = "sha256:a4785e48b045528f5bfe627b6ad554ff32def154f42372786903b7abcfe1aa16"}, + {file = "exceptiongroup-1.2.2-py3-none-any.whl", hash = "sha256:3111b9d131c238bec2f8f516e123e14ba243563fb135d3fe885990585aa7795b"}, + {file = "exceptiongroup-1.2.2.tar.gz", hash = "sha256:47c2edf7c6738fafb49fd34290706d1a1a2f4d1c6df275526b62cbb4aa5393cc"}, ] [package.extras] @@ -1292,13 +1291,13 @@ tests = ["asttokens (>=2.1.0)", "coverage", "coverage-enable-subprocess", "ipyth [[package]] name = "faker" -version = "25.2.0" +version = "26.0.0" description = "Faker is a Python package that generates fake data for you." optional = false python-versions = ">=3.8" files = [ - {file = "Faker-25.2.0-py3-none-any.whl", hash = "sha256:cfe97c4857c4c36ee32ea4aaabef884895992e209bae4cbd26807cf3e05c6918"}, - {file = "Faker-25.2.0.tar.gz", hash = "sha256:45b84f47ff1ef86e3d1a8d11583ca871ecf6730fad0660edadc02576583a2423"}, + {file = "Faker-26.0.0-py3-none-any.whl", hash = "sha256:886ee28219be96949cd21ecc96c4c742ee1680e77f687b095202c8def1a08f06"}, + {file = "Faker-26.0.0.tar.gz", hash = "sha256:0f60978314973de02c00474c2ae899785a42b2cf4f41b7987e93c132a2b8a4a9"}, ] [package.dependencies] @@ -1331,13 +1330,13 @@ files = [ [[package]] name = "fastapi" -version = "0.111.0" +version = "0.111.1" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.111.0-py3-none-any.whl", hash = "sha256:97ecbf994be0bcbdadedf88c3150252bed7b2087075ac99735403b1b76cc8fc0"}, - {file = "fastapi-0.111.0.tar.gz", hash = "sha256:b9db9dd147c91cb8b769f7183535773d8741dd46f9dc6676cd82eab510228cd7"}, + {file = "fastapi-0.111.1-py3-none-any.whl", hash = "sha256:4f51cfa25d72f9fbc3280832e84b32494cf186f50158d364a8765aabf22587bf"}, + {file = "fastapi-0.111.1.tar.gz", hash = "sha256:ddd1ac34cb1f76c2e2d7f8545a4bcb5463bce4834e81abf0b189e0c359ab2413"}, ] [package.dependencies] @@ -1345,12 +1344,10 @@ email_validator = ">=2.0.0" fastapi-cli = ">=0.0.2" httpx = ">=0.23.0" jinja2 = ">=2.11.2" -orjson = ">=3.2.1" pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" python-multipart = ">=0.0.7" starlette = ">=0.37.2,<0.38.0" typing-extensions = ">=4.8.0" -ujson = ">=4.0.1,<4.0.2 || >4.0.2,<4.1.0 || >4.1.0,<4.2.0 || >4.2.0,<4.3.0 || >4.3.0,<5.0.0 || >5.0.0,<5.1.0 || >5.1.0" uvicorn = {version = ">=0.12.0", extras = ["standard"]} [package.extras] @@ -1375,13 +1372,13 @@ standard = ["fastapi", "uvicorn[standard] (>=0.15.0)"] [[package]] name = "fastjsonschema" -version = "2.19.1" +version = "2.20.0" description = "Fastest Python implementation of JSON schema" optional = false python-versions = "*" files = [ - {file = "fastjsonschema-2.19.1-py3-none-any.whl", hash = "sha256:3672b47bc94178c9f23dbb654bf47440155d4db9df5f7bc47643315f9c405cd0"}, - {file = "fastjsonschema-2.19.1.tar.gz", hash = "sha256:e3126a94bdc4623d3de4485f8d468a12f02a67921315ddc87836d6e456dc789d"}, + {file = "fastjsonschema-2.20.0-py3-none-any.whl", hash = "sha256:5875f0b0fa7a0043a91e93a9b8f793bcbbba9691e7fd83dca95c28ba26d21f0a"}, + {file = "fastjsonschema-2.20.0.tar.gz", hash = "sha256:3d48fc5300ee96f5d116f10fe6f28d938e6008f59a6a025c2649475b87f76a23"}, ] [package.extras] @@ -1389,18 +1386,18 @@ devel = ["colorama", "json-spec", "jsonschema", "pylint", "pytest", "pytest-benc [[package]] name = "filelock" -version = "3.14.0" +version = "3.15.4" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.14.0-py3-none-any.whl", hash = "sha256:43339835842f110ca7ae60f1e1c160714c5a6afd15a2873419ab185334975c0f"}, - {file = "filelock-3.14.0.tar.gz", hash = "sha256:6ea72da3be9b8c82afd3edcf99f2fffbb5076335a5ae4d03248bb5b6c3eae78a"}, + {file = "filelock-3.15.4-py3-none-any.whl", hash = "sha256:6ca1fffae96225dab4c6eaf1c4f4f28cd2568d3ec2a44e15a08520504de468e7"}, + {file = "filelock-3.15.4.tar.gz", hash = "sha256:2207938cbc1844345cb01a5a95524dae30f0ce089eba5b00378295a17e3e90cb"}, ] [package.extras] docs = ["furo (>=2023.9.10)", "sphinx (>=7.2.6)", "sphinx-autodoc-typehints (>=1.25.2)"] -testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)"] +testing = ["covdefaults (>=2.3)", "coverage (>=7.3.2)", "diff-cover (>=8.0.1)", "pytest (>=7.4.3)", "pytest-asyncio (>=0.21)", "pytest-cov (>=4.1)", "pytest-mock (>=3.12)", "pytest-timeout (>=2.2)", "virtualenv (>=20.26.2)"] typing = ["typing-extensions (>=4.8)"] [[package]] @@ -1691,13 +1688,13 @@ socks = ["socksio (==1.*)"] [[package]] name = "hypercorn" -version = "0.17.2" +version = "0.17.3" description = "A ASGI Server based on Hyper libraries and inspired by Gunicorn" optional = false python-versions = ">=3.8" files = [ - {file = "hypercorn-0.17.2-py3-none-any.whl", hash = "sha256:eaa97b13c1fd8857cf31af34640704382ce3ed53cff6b3192869ea5f8244c6b1"}, - {file = "hypercorn-0.17.2.tar.gz", hash = "sha256:3827860f7e0cf0320a1288f0762c10483617de19dae08cfc3fbeb2b3323a6ffb"}, + {file = "hypercorn-0.17.3-py3-none-any.whl", hash = "sha256:059215dec34537f9d40a69258d323f56344805efb462959e727152b0aa504547"}, + {file = "hypercorn-0.17.3.tar.gz", hash = "sha256:1b37802ee3ac52d2d85270700d565787ab16cf19e1462ccfa9f089ca17574165"}, ] [package.dependencies] @@ -1714,7 +1711,7 @@ wsproto = ">=0.14.0" docs = ["pydata_sphinx_theme", "sphinxcontrib_mermaid"] h3 = ["aioquic (>=0.9.0,<1.0)"] trio = ["trio (>=0.22.0)"] -uvloop = ["uvloop"] +uvloop = ["uvloop (>=0.18)"] [[package]] name = "hyperframe" @@ -1754,22 +1751,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.0.0" +version = "7.1.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.0.0-py3-none-any.whl", hash = "sha256:d97503976bb81f40a193d41ee6570868479c69d5068651eb039c40d850c59d67"}, - {file = "importlib_metadata-7.0.0.tar.gz", hash = "sha256:7fc841f8b8332803464e5dc1c63a2e59121f46ca186c0e2e182e80bf8c1319f7"}, + {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, + {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (<7.2.5)", "sphinx (>=3.5)", "sphinx-lint"] +docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] perf = ["ipython"] -testing = ["flufl.flake8", "importlib-resources (>=1.3)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-black (>=0.3.7)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy (>=0.9.1)", "pytest-perf (>=0.9.2)", "pytest-ruff"] +testing = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "importlib-resources" @@ -1817,13 +1814,13 @@ files = [ [[package]] name = "inline-snapshot" -version = "0.10.1" +version = "0.10.2" description = "golden master/snapshot/approval testing library which puts the values right into your source code" optional = false python-versions = ">=3.8" files = [ - {file = "inline_snapshot-0.10.1-py3-none-any.whl", hash = "sha256:061e11be3fe9e99296ac3caf7c6d458509b02474d5bfa40b67c762062aeb3fbe"}, - {file = "inline_snapshot-0.10.1.tar.gz", hash = "sha256:f69ba81d150d057913540bc1ec7f7b1910c6f1df1c0d547751e411be62b2d198"}, + {file = "inline_snapshot-0.10.2-py3-none-any.whl", hash = "sha256:f61d42f0d4bddd2a3efae041f5b168e94ac2df566cbf2c67a26d03d5f090835a"}, + {file = "inline_snapshot-0.10.2.tar.gz", hash = "sha256:fb3c1410a08c9700ca838a269f70117760b024d99d6193661a8b47f8302b09cd"}, ] [package.dependencies] @@ -2022,13 +2019,13 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.9.1)", "build (>=0.10.0)", "coverage (>= [[package]] name = "litestar" -version = "2.8.3" +version = "2.9.1" description = "Litestar - A production-ready, highly performant, extensible ASGI API Framework" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "litestar-2.8.3-py3-none-any.whl", hash = "sha256:bef5e8592b1afba24306f9a5834d84cef89826b12f58a97d3099cf49e2f3767d"}, - {file = "litestar-2.8.3.tar.gz", hash = "sha256:3764eef3885b331bfb15c478a2b9e2bc1980741ff58bd5512d599436f669549c"}, + {file = "litestar-2.9.1-py3-none-any.whl", hash = "sha256:fe3e4ec91a9c24af652775fed5fa4d789902f165cabbd7d2e62821fec1f69462"}, + {file = "litestar-2.9.1.tar.gz", hash = "sha256:7c13bb4dd7b1c77f6c462262cfe401ca6429eab3e4d98f38586b68268bd5ac97"}, ] [package.dependencies] @@ -2052,7 +2049,7 @@ attrs = ["attrs"] brotli = ["brotli"] cli = ["jsbeautifier", "uvicorn[standard]", "uvloop (>=0.18.0)"] cryptography = ["cryptography"] -full = ["advanced-alchemy (>=0.2.2,<0.9.0)", "annotated-types", "attrs", "brotli", "cryptography", "email-validator", "fast-query-parsers (>=1.0.2)", "jinja2", "jinja2 (>=3.1.2)", "jsbeautifier", "mako (>=1.2.4)", "minijinja (>=1.0.0)", "opentelemetry-instrumentation-asgi", "piccolo", "picologging", "prometheus-client", "pydantic", "pydantic-extra-types", "python-jose", "redis[hiredis] (>=4.4.4)", "structlog", "uvicorn[standard]", "uvloop (>=0.18.0)"] +full = ["advanced-alchemy (>=0.2.2)", "annotated-types", "attrs", "brotli", "cryptography", "email-validator", "fast-query-parsers (>=1.0.2)", "jinja2", "jinja2 (>=3.1.2)", "jsbeautifier", "mako (>=1.2.4)", "minijinja (>=1.0.0)", "opentelemetry-instrumentation-asgi", "piccolo", "picologging", "prometheus-client", "pydantic", "pydantic-extra-types", "python-jose", "redis[hiredis] (>=4.4.4)", "structlog", "uvicorn[standard]", "uvloop (>=0.18.0)"] jinja = ["jinja2 (>=3.1.2)"] jwt = ["cryptography", "python-jose"] mako = ["mako (>=1.2.4)"] @@ -2063,7 +2060,7 @@ picologging = ["picologging"] prometheus = ["prometheus-client"] pydantic = ["email-validator", "pydantic", "pydantic-extra-types"] redis = ["redis[hiredis] (>=4.4.4)"] -sqlalchemy = ["advanced-alchemy (>=0.2.2,<0.9.0)"] +sqlalchemy = ["advanced-alchemy (>=0.2.2)"] standard = ["fast-query-parsers (>=1.0.2)", "jinja2", "jsbeautifier", "uvicorn[standard]", "uvloop (>=0.18.0)"] structlog = ["structlog"] @@ -2192,13 +2189,13 @@ files = [ [[package]] name = "more-itertools" -version = "10.2.0" +version = "10.3.0" description = "More routines for operating on iterables, beyond itertools" optional = false python-versions = ">=3.8" files = [ - {file = "more-itertools-10.2.0.tar.gz", hash = "sha256:8fccb480c43d3e99a00087634c06dd02b0d50fbf088b380de5a41a015ec239e1"}, - {file = "more_itertools-10.2.0-py3-none-any.whl", hash = "sha256:686b06abe565edfab151cb8fd385a05651e1fdf8f0a14191e4439283421f8684"}, + {file = "more-itertools-10.3.0.tar.gz", hash = "sha256:e5d93ef411224fbcef366a6e8ddc4c5781bc6359d43412a65dd5964e46111463"}, + {file = "more_itertools-10.3.0-py3-none-any.whl", hash = "sha256:ea6a02e24a9161e51faad17a8782b92a0df82c12c1c8886fec7f0c3fa1a1b320"}, ] [[package]] @@ -2466,110 +2463,58 @@ tomlkit = ">=0.7" [[package]] name = "opentelemetry-api" -version = "1.24.0" +version = "1.25.0" description = "OpenTelemetry Python API" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_api-1.24.0-py3-none-any.whl", hash = "sha256:0f2c363d98d10d1ce93330015ca7fd3a65f60be64e05e30f557c61de52c80ca2"}, - {file = "opentelemetry_api-1.24.0.tar.gz", hash = "sha256:42719f10ce7b5a9a73b10a4baf620574fb8ad495a9cbe5c18d76b75d8689c67e"}, + {file = "opentelemetry_api-1.25.0-py3-none-any.whl", hash = "sha256:757fa1aa020a0f8fa139f8959e53dec2051cc26b832e76fa839a6d76ecefd737"}, + {file = "opentelemetry_api-1.25.0.tar.gz", hash = "sha256:77c4985f62f2614e42ce77ee4c9da5fa5f0bc1e1821085e9a47533a9323ae869"}, ] [package.dependencies] deprecated = ">=1.2.6" -importlib-metadata = ">=6.0,<=7.0" +importlib-metadata = ">=6.0,<=7.1" [[package]] name = "opentelemetry-sdk" -version = "1.24.0" +version = "1.25.0" description = "OpenTelemetry Python SDK" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_sdk-1.24.0-py3-none-any.whl", hash = "sha256:fa731e24efe832e98bcd90902085b359dcfef7d9c9c00eb5b9a18587dae3eb59"}, - {file = "opentelemetry_sdk-1.24.0.tar.gz", hash = "sha256:75bc0563affffa827700e0f4f4a68e1e257db0df13372344aebc6f8a64cde2e5"}, + {file = "opentelemetry_sdk-1.25.0-py3-none-any.whl", hash = "sha256:d97ff7ec4b351692e9d5a15af570c693b8715ad78b8aafbec5c7100fe966b4c9"}, + {file = "opentelemetry_sdk-1.25.0.tar.gz", hash = "sha256:ce7fc319c57707ef5bf8b74fb9f8ebdb8bfafbe11898410e0d2a761d08a98ec7"}, ] [package.dependencies] -opentelemetry-api = "1.24.0" -opentelemetry-semantic-conventions = "0.45b0" +opentelemetry-api = "1.25.0" +opentelemetry-semantic-conventions = "0.46b0" typing-extensions = ">=3.7.4" [[package]] name = "opentelemetry-semantic-conventions" -version = "0.45b0" +version = "0.46b0" description = "OpenTelemetry Semantic Conventions" optional = false python-versions = ">=3.8" files = [ - {file = "opentelemetry_semantic_conventions-0.45b0-py3-none-any.whl", hash = "sha256:a4a6fb9a7bacd9167c082aa4681009e9acdbfa28ffb2387af50c2fef3d30c864"}, - {file = "opentelemetry_semantic_conventions-0.45b0.tar.gz", hash = "sha256:7c84215a44ac846bc4b8e32d5e78935c5c43482e491812a0bb8aaf87e4d92118"}, + {file = "opentelemetry_semantic_conventions-0.46b0-py3-none-any.whl", hash = "sha256:6daef4ef9fa51d51855d9f8e0ccd3a1bd59e0e545abe99ac6203804e36ab3e07"}, + {file = "opentelemetry_semantic_conventions-0.46b0.tar.gz", hash = "sha256:fbc982ecbb6a6e90869b15c1673be90bd18c8a56ff1cffc0864e38e2edffaefa"}, ] -[[package]] -name = "orjson" -version = "3.10.3" -description = "Fast, correct Python JSON library supporting dataclasses, datetimes, and numpy" -optional = false -python-versions = ">=3.8" -files = [ - {file = "orjson-3.10.3-cp310-cp310-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9fb6c3f9f5490a3eb4ddd46fc1b6eadb0d6fc16fb3f07320149c3286a1409dd8"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:252124b198662eee80428f1af8c63f7ff077c88723fe206a25df8dc57a57b1fa"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9f3e87733823089a338ef9bbf363ef4de45e5c599a9bf50a7a9b82e86d0228da"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c8334c0d87103bb9fbbe59b78129f1f40d1d1e8355bbed2ca71853af15fa4ed3"}, - {file = "orjson-3.10.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1952c03439e4dce23482ac846e7961f9d4ec62086eb98ae76d97bd41d72644d7"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c0403ed9c706dcd2809f1600ed18f4aae50be263bd7112e54b50e2c2bc3ebd6d"}, - {file = "orjson-3.10.3-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:382e52aa4270a037d41f325e7d1dfa395b7de0c367800b6f337d8157367bf3a7"}, - {file = "orjson-3.10.3-cp310-none-win32.whl", hash = "sha256:be2aab54313752c04f2cbaab4515291ef5af8c2256ce22abc007f89f42f49109"}, - {file = "orjson-3.10.3-cp310-none-win_amd64.whl", hash = "sha256:416b195f78ae461601893f482287cee1e3059ec49b4f99479aedf22a20b1098b"}, - {file = "orjson-3.10.3-cp311-cp311-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:73100d9abbbe730331f2242c1fc0bcb46a3ea3b4ae3348847e5a141265479700"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:544a12eee96e3ab828dbfcb4d5a0023aa971b27143a1d35dc214c176fdfb29b3"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:520de5e2ef0b4ae546bea25129d6c7c74edb43fc6cf5213f511a927f2b28148b"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ccaa0a401fc02e8828a5bedfd80f8cd389d24f65e5ca3954d72c6582495b4bcf"}, - {file = "orjson-3.10.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9a7bc9e8bc11bac40f905640acd41cbeaa87209e7e1f57ade386da658092dc16"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:3582b34b70543a1ed6944aca75e219e1192661a63da4d039d088a09c67543b08"}, - {file = "orjson-3.10.3-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:1c23dfa91481de880890d17aa7b91d586a4746a4c2aa9a145bebdbaf233768d5"}, - {file = "orjson-3.10.3-cp311-none-win32.whl", hash = "sha256:1770e2a0eae728b050705206d84eda8b074b65ee835e7f85c919f5705b006c9b"}, - {file = "orjson-3.10.3-cp311-none-win_amd64.whl", hash = "sha256:93433b3c1f852660eb5abdc1f4dd0ced2be031ba30900433223b28ee0140cde5"}, - {file = "orjson-3.10.3-cp312-cp312-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:a39aa73e53bec8d410875683bfa3a8edf61e5a1c7bb4014f65f81d36467ea098"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0943a96b3fa09bee1afdfccc2cb236c9c64715afa375b2af296c73d91c23eab2"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:e852baafceff8da3c9defae29414cc8513a1586ad93e45f27b89a639c68e8176"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:18566beb5acd76f3769c1d1a7ec06cdb81edc4d55d2765fb677e3eaa10fa99e0"}, - {file = "orjson-3.10.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1bd2218d5a3aa43060efe649ec564ebedec8ce6ae0a43654b81376216d5ebd42"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cf20465e74c6e17a104ecf01bf8cd3b7b252565b4ccee4548f18b012ff2f8069"}, - {file = "orjson-3.10.3-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:ba7f67aa7f983c4345eeda16054a4677289011a478ca947cd69c0a86ea45e534"}, - {file = "orjson-3.10.3-cp312-none-win32.whl", hash = "sha256:17e0713fc159abc261eea0f4feda611d32eabc35708b74bef6ad44f6c78d5ea0"}, - {file = "orjson-3.10.3-cp312-none-win_amd64.whl", hash = "sha256:4c895383b1ec42b017dd2c75ae8a5b862fc489006afde06f14afbdd0309b2af0"}, - {file = "orjson-3.10.3-cp38-cp38-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:be2719e5041e9fb76c8c2c06b9600fe8e8584e6980061ff88dcbc2691a16d20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0175a5798bdc878956099f5c54b9837cb62cfbf5d0b86ba6d77e43861bcec2"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:978be58a68ade24f1af7758626806e13cff7748a677faf95fbb298359aa1e20d"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16bda83b5c61586f6f788333d3cf3ed19015e3b9019188c56983b5a299210eb5"}, - {file = "orjson-3.10.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4ad1f26bea425041e0a1adad34630c4825a9e3adec49079b1fb6ac8d36f8b754"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:9e253498bee561fe85d6325ba55ff2ff08fb5e7184cd6a4d7754133bd19c9195"}, - {file = "orjson-3.10.3-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:0a62f9968bab8a676a164263e485f30a0b748255ee2f4ae49a0224be95f4532b"}, - {file = "orjson-3.10.3-cp38-none-win32.whl", hash = "sha256:8d0b84403d287d4bfa9bf7d1dc298d5c1c5d9f444f3737929a66f2fe4fb8f134"}, - {file = "orjson-3.10.3-cp38-none-win_amd64.whl", hash = "sha256:8bc7a4df90da5d535e18157220d7915780d07198b54f4de0110eca6b6c11e290"}, - {file = "orjson-3.10.3-cp39-cp39-macosx_10_15_x86_64.macosx_11_0_arm64.macosx_10_15_universal2.whl", hash = "sha256:9059d15c30e675a58fdcd6f95465c1522b8426e092de9fff20edebfdc15e1cb0"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8d40c7f7938c9c2b934b297412c067936d0b54e4b8ab916fd1a9eb8f54c02294"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d4a654ec1de8fdaae1d80d55cee65893cb06494e124681ab335218be6a0691e7"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:831c6ef73f9aa53c5f40ae8f949ff7681b38eaddb6904aab89dca4d85099cb78"}, - {file = "orjson-3.10.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:99b880d7e34542db89f48d14ddecbd26f06838b12427d5a25d71baceb5ba119d"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:2e5e176c994ce4bd434d7aafb9ecc893c15f347d3d2bbd8e7ce0b63071c52e25"}, - {file = "orjson-3.10.3-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b69a58a37dab856491bf2d3bbf259775fdce262b727f96aafbda359cb1d114d8"}, - {file = "orjson-3.10.3-cp39-none-win32.whl", hash = "sha256:b8d4d1a6868cde356f1402c8faeb50d62cee765a1f7ffcfd6de732ab0581e063"}, - {file = "orjson-3.10.3-cp39-none-win_amd64.whl", hash = "sha256:5102f50c5fc46d94f2033fe00d392588564378260d64377aec702f21a7a22912"}, - {file = "orjson-3.10.3.tar.gz", hash = "sha256:2b166507acae7ba2f7c315dcf185a9111ad5e992ac81f2d507aac39193c2c818"}, -] +[package.dependencies] +opentelemetry-api = "1.25.0" [[package]] name = "packaging" -version = "24.0" +version = "24.1" description = "Core utilities for Python packages" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "packaging-24.0-py3-none-any.whl", hash = "sha256:2ddfb553fdf02fb784c234c7ba6ccc288296ceabec964ad2eae3777778130bc5"}, - {file = "packaging-24.0.tar.gz", hash = "sha256:eb82c5e3e56209074766e6885bb04b8c38a0c015d0a30036ebe7ece34c9989e9"}, + {file = "packaging-24.1-py3-none-any.whl", hash = "sha256:5b8f2217dbdbd2f7f384c41c628544e6d52f2d0f53c6d0c3ea61aa5d1d7ff124"}, + {file = "packaging-24.1.tar.gz", hash = "sha256:026ed72c8ed3fcce5bf8950572258698927fd1dbda10a5e981cdf0ac37f4f002"}, ] [[package]] @@ -2599,24 +2544,24 @@ ptyprocess = ">=0.5" [[package]] name = "pip" -version = "23.3.2" +version = "24.0" description = "The PyPA recommended tool for installing Python packages." optional = false python-versions = ">=3.7" files = [ - {file = "pip-23.3.2-py3-none-any.whl", hash = "sha256:5052d7889c1f9d05224cd41741acb7c5d6fa735ab34e339624a614eaaa7e7d76"}, - {file = "pip-23.3.2.tar.gz", hash = "sha256:7fd9972f96db22c8077a1ee2691b172c8089b17a5652a44494a9ecb0d78f9149"}, + {file = "pip-24.0-py3-none-any.whl", hash = "sha256:ba0d021a166865d2265246961bec0152ff124de910c5cc39f1156ce3fa7c69dc"}, + {file = "pip-24.0.tar.gz", hash = "sha256:ea9bd1a847e8c5774a5777bb398c19e80bcd4e2aa16a4b301b718fe6f593aba2"}, ] [[package]] name = "pkginfo" -version = "1.10.0" +version = "1.11.1" description = "Query metadata from sdists / bdists / installed packages." optional = false -python-versions = ">=3.6" +python-versions = ">=3.8" files = [ - {file = "pkginfo-1.10.0-py3-none-any.whl", hash = "sha256:889a6da2ed7ffc58ab5b900d888ddce90bce912f2d2de1dc1c26f4cb9fe65097"}, - {file = "pkginfo-1.10.0.tar.gz", hash = "sha256:5df73835398d10db79f8eecd5cd86b1f6d29317589ea70796994d49399af6297"}, + {file = "pkginfo-1.11.1-py3-none-any.whl", hash = "sha256:bfa76a714fdfc18a045fcd684dbfc3816b603d9d075febef17cb6582bea29573"}, + {file = "pkginfo-1.11.1.tar.gz", hash = "sha256:2e0dca1cf4c8e39644eed32408ea9966ee15e0d324c62ba899a393b3c6b467aa"}, ] [package.extras] @@ -2718,13 +2663,13 @@ poetry-core = ">=1.7.0,<3.0.0" [[package]] name = "polyfactory" -version = "2.16.0" +version = "2.16.2" description = "Mock data generation factories" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "polyfactory-2.16.0-py3-none-any.whl", hash = "sha256:168d8e50b77e91e35e691e8b3eedac43d7e423a6857fa26d473def96d53f0ecf"}, - {file = "polyfactory-2.16.0.tar.gz", hash = "sha256:03d8c706b70c4782ac8e637d0f6ab52760a7d11b712da5936a95a8f7022b2688"}, + {file = "polyfactory-2.16.2-py3-none-any.whl", hash = "sha256:e5eaf97358fee07d0d8de86a93e81dc56e3be1e1514d145fea6c5f486cda6ea1"}, + {file = "polyfactory-2.16.2.tar.gz", hash = "sha256:6d0d90deb85e5bb1733ea8744c2d44eea2b31656e11b4fa73832d2e2ab5422da"}, ] [package.dependencies] @@ -2753,47 +2698,48 @@ files = [ [[package]] name = "protobuf" -version = "5.27.0" +version = "5.27.2" description = "" optional = false python-versions = ">=3.8" files = [ - {file = "protobuf-5.27.0-cp310-abi3-win32.whl", hash = "sha256:2f83bf341d925650d550b8932b71763321d782529ac0eaf278f5242f513cc04e"}, - {file = "protobuf-5.27.0-cp310-abi3-win_amd64.whl", hash = "sha256:b276e3f477ea1eebff3c2e1515136cfcff5ac14519c45f9b4aa2f6a87ea627c4"}, - {file = "protobuf-5.27.0-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:744489f77c29174328d32f8921566fb0f7080a2f064c5137b9d6f4b790f9e0c1"}, - {file = "protobuf-5.27.0-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:f51f33d305e18646f03acfdb343aac15b8115235af98bc9f844bf9446573827b"}, - {file = "protobuf-5.27.0-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:56937f97ae0dcf4e220ff2abb1456c51a334144c9960b23597f044ce99c29c89"}, - {file = "protobuf-5.27.0-cp38-cp38-win32.whl", hash = "sha256:a17f4d664ea868102feaa30a674542255f9f4bf835d943d588440d1f49a3ed15"}, - {file = "protobuf-5.27.0-cp38-cp38-win_amd64.whl", hash = "sha256:aabbbcf794fbb4c692ff14ce06780a66d04758435717107c387f12fb477bf0d8"}, - {file = "protobuf-5.27.0-cp39-cp39-win32.whl", hash = "sha256:587be23f1212da7a14a6c65fd61995f8ef35779d4aea9e36aad81f5f3b80aec5"}, - {file = "protobuf-5.27.0-cp39-cp39-win_amd64.whl", hash = "sha256:7cb65fc8fba680b27cf7a07678084c6e68ee13cab7cace734954c25a43da6d0f"}, - {file = "protobuf-5.27.0-py3-none-any.whl", hash = "sha256:673ad60f1536b394b4fa0bcd3146a4130fcad85bfe3b60eaa86d6a0ace0fa374"}, - {file = "protobuf-5.27.0.tar.gz", hash = "sha256:07f2b9a15255e3cf3f137d884af7972407b556a7a220912b252f26dc3121e6bf"}, + {file = "protobuf-5.27.2-cp310-abi3-win32.whl", hash = "sha256:354d84fac2b0d76062e9b3221f4abbbacdfd2a4d8af36bab0474f3a0bb30ab38"}, + {file = "protobuf-5.27.2-cp310-abi3-win_amd64.whl", hash = "sha256:0e341109c609749d501986b835f667c6e1e24531096cff9d34ae411595e26505"}, + {file = "protobuf-5.27.2-cp38-abi3-macosx_10_9_universal2.whl", hash = "sha256:a109916aaac42bff84702fb5187f3edadbc7c97fc2c99c5ff81dd15dcce0d1e5"}, + {file = "protobuf-5.27.2-cp38-abi3-manylinux2014_aarch64.whl", hash = "sha256:176c12b1f1c880bf7a76d9f7c75822b6a2bc3db2d28baa4d300e8ce4cde7409b"}, + {file = "protobuf-5.27.2-cp38-abi3-manylinux2014_x86_64.whl", hash = "sha256:b848dbe1d57ed7c191dfc4ea64b8b004a3f9ece4bf4d0d80a367b76df20bf36e"}, + {file = "protobuf-5.27.2-cp38-cp38-win32.whl", hash = "sha256:4fadd8d83e1992eed0248bc50a4a6361dc31bcccc84388c54c86e530b7f58863"}, + {file = "protobuf-5.27.2-cp38-cp38-win_amd64.whl", hash = "sha256:610e700f02469c4a997e58e328cac6f305f649826853813177e6290416e846c6"}, + {file = "protobuf-5.27.2-cp39-cp39-win32.whl", hash = "sha256:9e8f199bf7f97bd7ecebffcae45ebf9527603549b2b562df0fbc6d4d688f14ca"}, + {file = "protobuf-5.27.2-cp39-cp39-win_amd64.whl", hash = "sha256:7fc3add9e6003e026da5fc9e59b131b8f22b428b991ccd53e2af8071687b4fce"}, + {file = "protobuf-5.27.2-py3-none-any.whl", hash = "sha256:54330f07e4949d09614707c48b06d1a22f8ffb5763c159efd5c0928326a91470"}, + {file = "protobuf-5.27.2.tar.gz", hash = "sha256:f3ecdef226b9af856075f28227ff2c90ce3a594d092c39bee5513573f25e2714"}, ] [[package]] name = "psutil" -version = "5.9.8" +version = "6.0.0" description = "Cross-platform lib for process and system monitoring in Python." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" -files = [ - {file = "psutil-5.9.8-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:26bd09967ae00920df88e0352a91cff1a78f8d69b3ecabbfe733610c0af486c8"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:05806de88103b25903dff19bb6692bd2e714ccf9e668d050d144012055cbca73"}, - {file = "psutil-5.9.8-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:611052c4bc70432ec770d5d54f64206aa7203a101ec273a0cd82418c86503bb7"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:50187900d73c1381ba1454cf40308c2bf6f34268518b3f36a9b663ca87e65e36"}, - {file = "psutil-5.9.8-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:02615ed8c5ea222323408ceba16c60e99c3f91639b07da6373fb7e6539abc56d"}, - {file = "psutil-5.9.8-cp27-none-win32.whl", hash = "sha256:36f435891adb138ed3c9e58c6af3e2e6ca9ac2f365efe1f9cfef2794e6c93b4e"}, - {file = "psutil-5.9.8-cp27-none-win_amd64.whl", hash = "sha256:bd1184ceb3f87651a67b2708d4c3338e9b10c5df903f2e3776b62303b26cb631"}, - {file = "psutil-5.9.8-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:aee678c8720623dc456fa20659af736241f575d79429a0e5e9cf88ae0605cc81"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8cb6403ce6d8e047495a701dc7c5bd788add903f8986d523e3e20b98b733e421"}, - {file = "psutil-5.9.8-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d06016f7f8625a1825ba3732081d77c94589dca78b7a3fc072194851e88461a4"}, - {file = "psutil-5.9.8-cp36-cp36m-win32.whl", hash = "sha256:7d79560ad97af658a0f6adfef8b834b53f64746d45b403f225b85c5c2c140eee"}, - {file = "psutil-5.9.8-cp36-cp36m-win_amd64.whl", hash = "sha256:27cc40c3493bb10de1be4b3f07cae4c010ce715290a5be22b98493509c6299e2"}, - {file = "psutil-5.9.8-cp37-abi3-win32.whl", hash = "sha256:bc56c2a1b0d15aa3eaa5a60c9f3f8e3e565303b465dbf57a1b730e7a2b9844e0"}, - {file = "psutil-5.9.8-cp37-abi3-win_amd64.whl", hash = "sha256:8db4c1b57507eef143a15a6884ca10f7c73876cdf5d51e713151c1236a0e68cf"}, - {file = "psutil-5.9.8-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:d16bbddf0693323b8c6123dd804100241da461e41d6e332fb0ba6058f630f8c8"}, - {file = "psutil-5.9.8.tar.gz", hash = "sha256:6be126e3225486dff286a8fb9a06246a5253f4c7c53b475ea5f5ac934e64194c"}, +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" +files = [ + {file = "psutil-6.0.0-cp27-cp27m-macosx_10_9_x86_64.whl", hash = "sha256:a021da3e881cd935e64a3d0a20983bda0bb4cf80e4f74fa9bfcb1bc5785360c6"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_i686.whl", hash = "sha256:1287c2b95f1c0a364d23bc6f2ea2365a8d4d9b726a3be7294296ff7ba97c17f0"}, + {file = "psutil-6.0.0-cp27-cp27m-manylinux2010_x86_64.whl", hash = "sha256:a9a3dbfb4de4f18174528d87cc352d1f788b7496991cca33c6996f40c9e3c92c"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_i686.whl", hash = "sha256:6ec7588fb3ddaec7344a825afe298db83fe01bfaaab39155fa84cf1c0d6b13c3"}, + {file = "psutil-6.0.0-cp27-cp27mu-manylinux2010_x86_64.whl", hash = "sha256:1e7c870afcb7d91fdea2b37c24aeb08f98b6d67257a5cb0a8bc3ac68d0f1a68c"}, + {file = "psutil-6.0.0-cp27-none-win32.whl", hash = "sha256:02b69001f44cc73c1c5279d02b30a817e339ceb258ad75997325e0e6169d8b35"}, + {file = "psutil-6.0.0-cp27-none-win_amd64.whl", hash = "sha256:21f1fb635deccd510f69f485b87433460a603919b45e2a324ad65b0cc74f8fb1"}, + {file = "psutil-6.0.0-cp36-abi3-macosx_10_9_x86_64.whl", hash = "sha256:c588a7e9b1173b6e866756dde596fd4cad94f9399daf99ad8c3258b3cb2b47a0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_i686.manylinux2010_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ed2440ada7ef7d0d608f20ad89a04ec47d2d3ab7190896cd62ca5fc4fe08bf0"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_12_x86_64.manylinux2010_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5fd9a97c8e94059b0ef54a7d4baf13b405011176c3b6ff257c247cae0d560ecd"}, + {file = "psutil-6.0.0-cp36-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e2e8d0054fc88153ca0544f5c4d554d42e33df2e009c4ff42284ac9ebdef4132"}, + {file = "psutil-6.0.0-cp36-cp36m-win32.whl", hash = "sha256:fc8c9510cde0146432bbdb433322861ee8c3efbf8589865c8bf8d21cb30c4d14"}, + {file = "psutil-6.0.0-cp36-cp36m-win_amd64.whl", hash = "sha256:34859b8d8f423b86e4385ff3665d3f4d94be3cdf48221fbe476e883514fdb71c"}, + {file = "psutil-6.0.0-cp37-abi3-win32.whl", hash = "sha256:a495580d6bae27291324fe60cea0b5a7c23fa36a7cd35035a16d93bdcf076b9d"}, + {file = "psutil-6.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:33ea5e1c975250a720b3a6609c490db40dae5d83a4eb315170c4fe0d8b1f34b3"}, + {file = "psutil-6.0.0-cp38-abi3-macosx_11_0_arm64.whl", hash = "sha256:ffe7fc9b6b36beadc8c322f84e1caff51e8703b88eee1da46d1e3a6ae11b4fd0"}, + {file = "psutil-6.0.0.tar.gz", hash = "sha256:8faae4f310b6d969fa26ca0545338b21f73c6b15db7c4a8d934a5482faa818f2"}, ] [package.extras] @@ -2848,109 +2794,122 @@ files = [ [[package]] name = "pydantic" -version = "2.7.1" +version = "2.8.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.7.1-py3-none-any.whl", hash = "sha256:e029badca45266732a9a79898a15ae2e8b14840b1eabbb25844be28f0b33f3d5"}, - {file = "pydantic-2.7.1.tar.gz", hash = "sha256:e9dbb5eada8abe4d9ae5f46b9939aead650cd2b68f249bb3a8139dbe125803cc"}, + {file = "pydantic-2.8.2-py3-none-any.whl", hash = "sha256:73ee9fddd406dc318b885c7a2eab8a6472b68b8fb5ba8150949fc3db939f23c8"}, + {file = "pydantic-2.8.2.tar.gz", hash = "sha256:6f62c13d067b0755ad1c21a34bdd06c0c12625a22b0fc09c6b149816604f7c2a"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.2" -typing-extensions = ">=4.6.1" +pydantic-core = "2.20.1" +typing-extensions = [ + {version = ">=4.6.1", markers = "python_version < \"3.13\""}, + {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, +] [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.2" +version = "2.20.1" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:9e08e867b306f525802df7cd16c44ff5ebbe747ff0ca6cf3fde7f36c05a59a81"}, - {file = "pydantic_core-2.18.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:f0a21cbaa69900cbe1a2e7cad2aa74ac3cf21b10c3efb0fa0b80305274c0e8a2"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0680b1f1f11fda801397de52c36ce38ef1c1dc841a0927a94f226dea29c3ae3d"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:95b9d5e72481d3780ba3442eac863eae92ae43a5f3adb5b4d0a1de89d42bb250"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c4fcf5cd9c4b655ad666ca332b9a081112cd7a58a8b5a6ca7a3104bc950f2038"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9b5155ff768083cb1d62f3e143b49a8a3432e6789a3abee8acd005c3c7af1c74"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:553ef617b6836fc7e4df130bb851e32fe357ce36336d897fd6646d6058d980af"}, - {file = "pydantic_core-2.18.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89ed9eb7d616ef5714e5590e6cf7f23b02d0d539767d33561e3675d6f9e3857"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:75f7e9488238e920ab6204399ded280dc4c307d034f3924cd7f90a38b1829563"}, - {file = "pydantic_core-2.18.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:ef26c9e94a8c04a1b2924149a9cb081836913818e55681722d7f29af88fe7b38"}, - {file = "pydantic_core-2.18.2-cp310-none-win32.whl", hash = "sha256:182245ff6b0039e82b6bb585ed55a64d7c81c560715d1bad0cbad6dfa07b4027"}, - {file = "pydantic_core-2.18.2-cp310-none-win_amd64.whl", hash = "sha256:e23ec367a948b6d812301afc1b13f8094ab7b2c280af66ef450efc357d2ae543"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:219da3f096d50a157f33645a1cf31c0ad1fe829a92181dd1311022f986e5fbe3"}, - {file = "pydantic_core-2.18.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:cc1cfd88a64e012b74e94cd00bbe0f9c6df57049c97f02bb07d39e9c852e19a4"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:05b7133a6e6aeb8df37d6f413f7705a37ab4031597f64ab56384c94d98fa0e90"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:224c421235f6102e8737032483f43c1a8cfb1d2f45740c44166219599358c2cd"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b14d82cdb934e99dda6d9d60dc84a24379820176cc4a0d123f88df319ae9c150"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2728b01246a3bba6de144f9e3115b532ee44bd6cf39795194fb75491824a1413"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:470b94480bb5ee929f5acba6995251ada5e059a5ef3e0dfc63cca287283ebfa6"}, - {file = "pydantic_core-2.18.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:997abc4df705d1295a42f95b4eec4950a37ad8ae46d913caeee117b6b198811c"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:75250dbc5290e3f1a0f4618db35e51a165186f9034eff158f3d490b3fed9f8a0"}, - {file = "pydantic_core-2.18.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:4456f2dca97c425231d7315737d45239b2b51a50dc2b6f0c2bb181fce6207664"}, - {file = "pydantic_core-2.18.2-cp311-none-win32.whl", hash = "sha256:269322dcc3d8bdb69f054681edff86276b2ff972447863cf34c8b860f5188e2e"}, - {file = "pydantic_core-2.18.2-cp311-none-win_amd64.whl", hash = "sha256:800d60565aec896f25bc3cfa56d2277d52d5182af08162f7954f938c06dc4ee3"}, - {file = "pydantic_core-2.18.2-cp311-none-win_arm64.whl", hash = "sha256:1404c69d6a676245199767ba4f633cce5f4ad4181f9d0ccb0577e1f66cf4c46d"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:fb2bd7be70c0fe4dfd32c951bc813d9fe6ebcbfdd15a07527796c8204bd36242"}, - {file = "pydantic_core-2.18.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:6132dd3bd52838acddca05a72aafb6eab6536aa145e923bb50f45e78b7251043"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7d904828195733c183d20a54230c0df0eb46ec746ea1a666730787353e87182"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c9bd70772c720142be1020eac55f8143a34ec9f82d75a8e7a07852023e46617f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:2b8ed04b3582771764538f7ee7001b02e1170223cf9b75dff0bc698fadb00cf3"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e6dac87ddb34aaec85f873d737e9d06a3555a1cc1a8e0c44b7f8d5daeb89d86f"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7ca4ae5a27ad7a4ee5170aebce1574b375de390bc01284f87b18d43a3984df72"}, - {file = "pydantic_core-2.18.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:886eec03591b7cf058467a70a87733b35f44707bd86cf64a615584fd72488b7c"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ca7b0c1f1c983e064caa85f3792dd2fe3526b3505378874afa84baf662e12241"}, - {file = "pydantic_core-2.18.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:4b4356d3538c3649337df4074e81b85f0616b79731fe22dd11b99499b2ebbdf3"}, - {file = "pydantic_core-2.18.2-cp312-none-win32.whl", hash = "sha256:8b172601454f2d7701121bbec3425dd71efcb787a027edf49724c9cefc14c038"}, - {file = "pydantic_core-2.18.2-cp312-none-win_amd64.whl", hash = "sha256:b1bd7e47b1558ea872bd16c8502c414f9e90dcf12f1395129d7bb42a09a95438"}, - {file = "pydantic_core-2.18.2-cp312-none-win_arm64.whl", hash = "sha256:98758d627ff397e752bc339272c14c98199c613f922d4a384ddc07526c86a2ec"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:9fdad8e35f278b2c3eb77cbdc5c0a49dada440657bf738d6905ce106dc1de439"}, - {file = "pydantic_core-2.18.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:1d90c3265ae107f91a4f279f4d6f6f1d4907ac76c6868b27dc7fb33688cfb347"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:390193c770399861d8df9670fb0d1874f330c79caaca4642332df7c682bf6b91"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:82d5d4d78e4448683cb467897fe24e2b74bb7b973a541ea1dcfec1d3cbce39fb"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4774f3184d2ef3e14e8693194f661dea5a4d6ca4e3dc8e39786d33a94865cefd"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d4d938ec0adf5167cb335acb25a4ee69a8107e4984f8fbd2e897021d9e4ca21b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e0e8b1be28239fc64a88a8189d1df7fad8be8c1ae47fcc33e43d4be15f99cc70"}, - {file = "pydantic_core-2.18.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:868649da93e5a3d5eacc2b5b3b9235c98ccdbfd443832f31e075f54419e1b96b"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:78363590ef93d5d226ba21a90a03ea89a20738ee5b7da83d771d283fd8a56761"}, - {file = "pydantic_core-2.18.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:852e966fbd035a6468fc0a3496589b45e2208ec7ca95c26470a54daed82a0788"}, - {file = "pydantic_core-2.18.2-cp38-none-win32.whl", hash = "sha256:6a46e22a707e7ad4484ac9ee9f290f9d501df45954184e23fc29408dfad61350"}, - {file = "pydantic_core-2.18.2-cp38-none-win_amd64.whl", hash = "sha256:d91cb5ea8b11607cc757675051f61b3d93f15eca3cefb3e6c704a5d6e8440f4e"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ae0a8a797a5e56c053610fa7be147993fe50960fa43609ff2a9552b0e07013e8"}, - {file = "pydantic_core-2.18.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:042473b6280246b1dbf530559246f6842b56119c2926d1e52b631bdc46075f2a"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1a388a77e629b9ec814c1b1e6b3b595fe521d2cdc625fcca26fbc2d44c816804"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e25add29b8f3b233ae90ccef2d902d0ae0432eb0d45370fe315d1a5cf231004b"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f459a5ce8434614dfd39bbebf1041952ae01da6bed9855008cb33b875cb024c0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eff2de745698eb46eeb51193a9f41d67d834d50e424aef27df2fcdee1b153845"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a8309f67285bdfe65c372ea3722b7a5642680f3dba538566340a9d36e920b5f0"}, - {file = "pydantic_core-2.18.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f93a8a2e3938ff656a7c1bc57193b1319960ac015b6e87d76c76bf14fe0244b4"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:22057013c8c1e272eb8d0eebc796701167d8377441ec894a8fed1af64a0bf399"}, - {file = "pydantic_core-2.18.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:cfeecd1ac6cc1fb2692c3d5110781c965aabd4ec5d32799773ca7b1456ac636b"}, - {file = "pydantic_core-2.18.2-cp39-none-win32.whl", hash = "sha256:0d69b4c2f6bb3e130dba60d34c0845ba31b69babdd3f78f7c0c8fae5021a253e"}, - {file = "pydantic_core-2.18.2-cp39-none-win_amd64.whl", hash = "sha256:d9319e499827271b09b4e411905b24a426b8fb69464dfa1696258f53a3334641"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a1874c6dd4113308bd0eb568418e6114b252afe44319ead2b4081e9b9521fe75"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:ccdd111c03bfd3666bd2472b674c6899550e09e9f298954cfc896ab92b5b0e6d"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e18609ceaa6eed63753037fc06ebb16041d17d28199ae5aba0052c51449650a9"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6e5c584d357c4e2baf0ff7baf44f4994be121e16a2c88918a5817331fc7599d7"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43f0f463cf89ace478de71a318b1b4f05ebc456a9b9300d027b4b57c1a2064fb"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:e1b395e58b10b73b07b7cf740d728dd4ff9365ac46c18751bf8b3d8cca8f625a"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:0098300eebb1c837271d3d1a2cd2911e7c11b396eac9661655ee524a7f10587b"}, - {file = "pydantic_core-2.18.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:36789b70d613fbac0a25bb07ab3d9dba4d2e38af609c020cf4d888d165ee0bf3"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3f9a801e7c8f1ef8718da265bba008fa121243dfe37c1cea17840b0944dfd72c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:3a6515ebc6e69d85502b4951d89131ca4e036078ea35533bb76327f8424531ce"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:20aca1e2298c56ececfd8ed159ae4dde2df0781988c97ef77d5c16ff4bd5b400"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:223ee893d77a310a0391dca6df00f70bbc2f36a71a895cecd9a0e762dc37b349"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2334ce8c673ee93a1d6a65bd90327588387ba073c17e61bf19b4fd97d688d63c"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:cbca948f2d14b09d20268cda7b0367723d79063f26c4ffc523af9042cad95592"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b3ef08e20ec49e02d5c6717a91bb5af9b20f1805583cb0adfe9ba2c6b505b5ae"}, - {file = "pydantic_core-2.18.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:c6fdc8627910eed0c01aed6a390a252fe3ea6d472ee70fdde56273f198938374"}, - {file = "pydantic_core-2.18.2.tar.gz", hash = "sha256:2e29d20810dfc3043ee13ac7d9e25105799817683348823f305ab3f349b9386e"}, + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3acae97ffd19bf091c72df4d726d552c473f3576409b2a7ca36b2f535ffff4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:41f4c96227a67a013e7de5ff8f20fb496ce573893b7f4f2707d065907bffdbd6"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5f239eb799a2081495ea659d8d4a43a8f42cd1fe9ff2e7e436295c38a10c286a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:53e431da3fc53360db73eedf6f7124d1076e1b4ee4276b36fb25514544ceb4a3"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f1f62b2413c3a0e846c3b838b2ecd6c7a19ec6793b2a522745b0869e37ab5bc1"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5d41e6daee2813ecceea8eda38062d69e280b39df793f5a942fa515b8ed67953"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3d482efec8b7dc6bfaedc0f166b2ce349df0011f5d2f1f25537ced4cfc34fd98"}, + {file = "pydantic_core-2.20.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:e93e1a4b4b33daed65d781a57a522ff153dcf748dee70b40c7258c5861e1768a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:e7c4ea22b6739b162c9ecaaa41d718dfad48a244909fe7ef4b54c0b530effc5a"}, + {file = "pydantic_core-2.20.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4f2790949cf385d985a31984907fecb3896999329103df4e4983a4a41e13e840"}, + {file = "pydantic_core-2.20.1-cp310-none-win32.whl", hash = "sha256:5e999ba8dd90e93d57410c5e67ebb67ffcaadcea0ad973240fdfd3a135506250"}, + {file = "pydantic_core-2.20.1-cp310-none-win_amd64.whl", hash = "sha256:512ecfbefef6dac7bc5eaaf46177b2de58cdf7acac8793fe033b24ece0b9566c"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:d2a8fa9d6d6f891f3deec72f5cc668e6f66b188ab14bb1ab52422fe8e644f312"}, + {file = "pydantic_core-2.20.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:175873691124f3d0da55aeea1d90660a6ea7a3cfea137c38afa0a5ffabe37b88"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:37eee5b638f0e0dcd18d21f59b679686bbd18917b87db0193ae36f9c23c355fc"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:25e9185e2d06c16ee438ed39bf62935ec436474a6ac4f9358524220f1b236e43"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:150906b40ff188a3260cbee25380e7494ee85048584998c1e66df0c7a11c17a6"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:8ad4aeb3e9a97286573c03df758fc7627aecdd02f1da04516a86dc159bf70121"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d3f3ed29cd9f978c604708511a1f9c2fdcb6c38b9aae36a51905b8811ee5cbf1"}, + {file = "pydantic_core-2.20.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b0dae11d8f5ded51699c74d9548dcc5938e0804cc8298ec0aa0da95c21fff57b"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:faa6b09ee09433b87992fb5a2859efd1c264ddc37280d2dd5db502126d0e7f27"}, + {file = "pydantic_core-2.20.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:9dc1b507c12eb0481d071f3c1808f0529ad41dc415d0ca11f7ebfc666e66a18b"}, + {file = "pydantic_core-2.20.1-cp311-none-win32.whl", hash = "sha256:fa2fddcb7107e0d1808086ca306dcade7df60a13a6c347a7acf1ec139aa6789a"}, + {file = "pydantic_core-2.20.1-cp311-none-win_amd64.whl", hash = "sha256:40a783fb7ee353c50bd3853e626f15677ea527ae556429453685ae32280c19c2"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:595ba5be69b35777474fa07f80fc260ea71255656191adb22a8c53aba4479231"}, + {file = "pydantic_core-2.20.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:a4f55095ad087474999ee28d3398bae183a66be4823f753cd7d67dd0153427c9"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f9aa05d09ecf4c75157197f27cdc9cfaeb7c5f15021c6373932bf3e124af029f"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:e97fdf088d4b31ff4ba35db26d9cc472ac7ef4a2ff2badeabf8d727b3377fc52"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bc633a9fe1eb87e250b5c57d389cf28998e4292336926b0b6cdaee353f89a237"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d573faf8eb7e6b1cbbcb4f5b247c60ca8be39fe2c674495df0eb4318303137fe"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:26dc97754b57d2fd00ac2b24dfa341abffc380b823211994c4efac7f13b9e90e"}, + {file = "pydantic_core-2.20.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:33499e85e739a4b60c9dac710c20a08dc73cb3240c9a0e22325e671b27b70d24"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bebb4d6715c814597f85297c332297c6ce81e29436125ca59d1159b07f423eb1"}, + {file = "pydantic_core-2.20.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:516d9227919612425c8ef1c9b869bbbee249bc91912c8aaffb66116c0b447ebd"}, + {file = "pydantic_core-2.20.1-cp312-none-win32.whl", hash = "sha256:469f29f9093c9d834432034d33f5fe45699e664f12a13bf38c04967ce233d688"}, + {file = "pydantic_core-2.20.1-cp312-none-win_amd64.whl", hash = "sha256:035ede2e16da7281041f0e626459bcae33ed998cca6a0a007a5ebb73414ac72d"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:0827505a5c87e8aa285dc31e9ec7f4a17c81a813d45f70b1d9164e03a813a686"}, + {file = "pydantic_core-2.20.1-cp313-cp313-macosx_11_0_arm64.whl", hash = "sha256:19c0fa39fa154e7e0b7f82f88ef85faa2a4c23cc65aae2f5aea625e3c13c735a"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4aa223cd1e36b642092c326d694d8bf59b71ddddc94cdb752bbbb1c5c91d833b"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:c336a6d235522a62fef872c6295a42ecb0c4e1d0f1a3e500fe949415761b8a19"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7eb6a0587eded33aeefea9f916899d42b1799b7b14b8f8ff2753c0ac1741edac"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:70c8daf4faca8da5a6d655f9af86faf6ec2e1768f4b8b9d0226c02f3d6209703"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e9fa4c9bf273ca41f940bceb86922a7667cd5bf90e95dbb157cbb8441008482c"}, + {file = "pydantic_core-2.20.1-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:11b71d67b4725e7e2a9f6e9c0ac1239bbc0c48cce3dc59f98635efc57d6dac83"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:270755f15174fb983890c49881e93f8f1b80f0b5e3a3cc1394a255706cabd203"}, + {file = "pydantic_core-2.20.1-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:c81131869240e3e568916ef4c307f8b99583efaa60a8112ef27a366eefba8ef0"}, + {file = "pydantic_core-2.20.1-cp313-none-win32.whl", hash = "sha256:b91ced227c41aa29c672814f50dbb05ec93536abf8f43cd14ec9521ea09afe4e"}, + {file = "pydantic_core-2.20.1-cp313-none-win_amd64.whl", hash = "sha256:65db0f2eefcaad1a3950f498aabb4875c8890438bc80b19362cf633b87a8ab20"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:4745f4ac52cc6686390c40eaa01d48b18997cb130833154801a442323cc78f91"}, + {file = "pydantic_core-2.20.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a8ad4c766d3f33ba8fd692f9aa297c9058970530a32c728a2c4bfd2616d3358b"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41e81317dd6a0127cabce83c0c9c3fbecceae981c8391e6f1dec88a77c8a569a"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:04024d270cf63f586ad41fff13fde4311c4fc13ea74676962c876d9577bcc78f"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:eaad4ff2de1c3823fddf82f41121bdf453d922e9a238642b1dedb33c4e4f98ad"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:26ab812fa0c845df815e506be30337e2df27e88399b985d0bb4e3ecfe72df31c"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3c5ebac750d9d5f2706654c638c041635c385596caf68f81342011ddfa1e5598"}, + {file = "pydantic_core-2.20.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2aafc5a503855ea5885559eae883978c9b6d8c8993d67766ee73d82e841300dd"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:4868f6bd7c9d98904b748a2653031fc9c2f85b6237009d475b1008bfaeb0a5aa"}, + {file = "pydantic_core-2.20.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:aa2f457b4af386254372dfa78a2eda2563680d982422641a85f271c859df1987"}, + {file = "pydantic_core-2.20.1-cp38-none-win32.whl", hash = "sha256:225b67a1f6d602de0ce7f6c1c3ae89a4aa25d3de9be857999e9124f15dab486a"}, + {file = "pydantic_core-2.20.1-cp38-none-win_amd64.whl", hash = "sha256:6b507132dcfc0dea440cce23ee2182c0ce7aba7054576efc65634f080dbe9434"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:b03f7941783b4c4a26051846dea594628b38f6940a2fdc0df00b221aed39314c"}, + {file = "pydantic_core-2.20.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:1eedfeb6089ed3fad42e81a67755846ad4dcc14d73698c120a82e4ccf0f1f9f6"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:635fee4e041ab9c479e31edda27fcf966ea9614fff1317e280d99eb3e5ab6fe2"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:77bf3ac639c1ff567ae3b47f8d4cc3dc20f9966a2a6dd2311dcc055d3d04fb8a"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:7ed1b0132f24beeec5a78b67d9388656d03e6a7c837394f99257e2d55b461611"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:c6514f963b023aeee506678a1cf821fe31159b925c4b76fe2afa94cc70b3222b"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:10d4204d8ca33146e761c79f83cc861df20e7ae9f6487ca290a97702daf56006"}, + {file = "pydantic_core-2.20.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2d036c7187b9422ae5b262badb87a20a49eb6c5238b2004e96d4da1231badef1"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9ebfef07dbe1d93efb94b4700f2d278494e9162565a54f124c404a5656d7ff09"}, + {file = "pydantic_core-2.20.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6b9d9bb600328a1ce523ab4f454859e9d439150abb0906c5a1983c146580ebab"}, + {file = "pydantic_core-2.20.1-cp39-none-win32.whl", hash = "sha256:784c1214cb6dd1e3b15dd8b91b9a53852aed16671cc3fbe4786f4f1db07089e2"}, + {file = "pydantic_core-2.20.1-cp39-none-win_amd64.whl", hash = "sha256:d2fe69c5434391727efa54b47a1e7986bb0186e72a41b203df8f5b0a19a4f669"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:a45f84b09ac9c3d35dfcf6a27fd0634d30d183205230a0ebe8373a0e8cfa0906"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:d02a72df14dfdbaf228424573a07af10637bd490f0901cee872c4f434a735b94"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d2b27e6af28f07e2f195552b37d7d66b150adbaa39a6d327766ffd695799780f"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:084659fac3c83fd674596612aeff6041a18402f1e1bc19ca39e417d554468482"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:242b8feb3c493ab78be289c034a1f659e8826e2233786e36f2893a950a719bb6"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:38cf1c40a921d05c5edc61a785c0ddb4bed67827069f535d794ce6bcded919fc"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e0bbdd76ce9aa5d4209d65f2b27fc6e5ef1312ae6c5333c26db3f5ade53a1e99"}, + {file = "pydantic_core-2.20.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:254ec27fdb5b1ee60684f91683be95e5133c994cc54e86a0b0963afa25c8f8a6"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:407653af5617f0757261ae249d3fba09504d7a71ab36ac057c938572d1bc9331"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c693e916709c2465b02ca0ad7b387c4f8423d1db7b4649c551f27a529181c5ad"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5b5ff4911aea936a47d9376fd3ab17e970cc543d1b68921886e7f64bd28308d1"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177f55a886d74f1808763976ac4efd29b7ed15c69f4d838bbd74d9d09cf6fa86"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:964faa8a861d2664f0c7ab0c181af0bea66098b1919439815ca8803ef136fc4e"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:4dd484681c15e6b9a977c785a345d3e378d72678fd5f1f3c0509608da24f2ac0"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:f6d6cff3538391e8486a431569b77921adfcdef14eb18fbf19b7c0a5294d4e6a"}, + {file = "pydantic_core-2.20.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:a6d511cc297ff0883bc3708b465ff82d7560193169a8b93260f74ecb0a5e08a7"}, + {file = "pydantic_core-2.20.1.tar.gz", hash = "sha256:26ca695eeee5f9f1aeeb211ffc12f10bcb6f71e2989988fda61dabd65db878d4"}, ] [package.dependencies] @@ -3379,6 +3338,7 @@ files = [ {file = "PyYAML-6.0.1-cp311-cp311-win_amd64.whl", hash = "sha256:bf07ee2fef7014951eeb99f56f39c9bb4af143d8aa3c21b1677805985307da34"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:855fb52b0dc35af121542a76b9a84f8d1cd886ea97c84703eaa6d88e37a2ad28"}, {file = "PyYAML-6.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:40df9b996c2b73138957fe23a16a4f0ba614f4c0efce1e9406a184b6d07fa3a9"}, + {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a08c6f0fe150303c1c6b71ebcd7213c2858041a7e01975da3a99aed1e7a378ef"}, {file = "PyYAML-6.0.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c22bec3fbe2524cde73d7ada88f6566758a8f7227bfbf93a408a9d86bcc12a0"}, {file = "PyYAML-6.0.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8d4e9c88387b0f5c7d5f281e55304de64cf7f9c0021a3525bd3b1c542da3b0e4"}, {file = "PyYAML-6.0.1-cp312-cp312-win32.whl", hash = "sha256:d483d2cdf104e7c9fa60c544d92981f12ad66a457afae824d146093b8c294c54"}, @@ -3443,104 +3403,104 @@ dotenv = ["python-dotenv"] [[package]] name = "rapidfuzz" -version = "3.9.1" +version = "3.9.4" description = "rapid fuzzy string matching" optional = false python-versions = ">=3.8" files = [ - {file = "rapidfuzz-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:5f897a9bff517d5c6af6a90131796b4298b547b9a9a4df3cf285006be33aae5b"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:83c570ce23b447625929c0e7c4f2eab6d90f5a576db2b26a5aa0594a53d560ea"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4c6b6455ee8404a663e15477a8bfe98b1afb329ff224bcf6d15f623a3761b95"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aa44aef769e5834fef4fde091fd646cc1c52a2813b3aa241ae54b3028960abaa"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:25ea055ae40fb60f503f02b44b3ac35a39a9108be33f89e05b81bc4e3c849ec8"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fb592bad9d58b47c6681f0c180767d2c98775a35f7267131d33723139c3d6c2e"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb023adfefa62410fff877f7cc70cd4758cbfbad963e87d146cf71b022dce197"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:c883d2d2e31c759af1f3fdeb67ec151cf94e307f745b3d02ab3a2ef6595485f2"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:8e11405d81e8baea4999a5757a982009566cff8f6a121d5ccf042aab81ae0230"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:02ed579f35ddd3552c7f74bc0c10800b432d9b09a4cebb19fd7a10b3b4759cc0"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:9f8615a2a67a1f80b3aa7a3d7fbe6a2ed062a54c98988e3f9b664b49a3bc115e"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:64058f4a3698c6c8464df47a3b7da303db2477b2447142da3e67fc091f4c366a"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-win32.whl", hash = "sha256:2ef42c43c94139c890aeec40bc442c4bf8d48e15b456a88ce0f4cc5cfcad1896"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c99d001c45c31c2cd2f7361bc2036d3062b21db5f43beea8bc5109d43fe9f283"}, - {file = "rapidfuzz-3.9.1-cp310-cp310-win_arm64.whl", hash = "sha256:da3f495cf4f7a443b34a6d3c6805265595fcd13641b3253a8e2034289d828dd9"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:f8869dcf072227a40a6f9e87b3fc4eb020055a08ad12b63d751c354e3a973ccb"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:9f66f9d5f14141b4b017e76118ec4bda29266f6b281989026e3a9ba1a2aaf032"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07decc6b058f935d2219423a50aac426027928cc734809f793bc250de4a3756e"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c125095d1828fa10ac79077594dd2d8829167d9e184e20baa97620fc52ebdcc9"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:76a55bcc3abc9f8e38a1218cb5a09719126cfc4cba23ebd8caa27dfdc69cedd8"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:50c2f7ad132dfeb6247c90b41431662af939a820f761cf930708d55912377ed8"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:177bddf50577db59bcb00b6f7a5c2b70f2ec5a2aba40c8add7a6f7fd8609224e"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:dec2792f864be731c8339cad99001caa6540aa909e6fd8bc688bb0419c501f44"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:c6437cba4b9460d5ee0bafd796e13ef9307091b81685bbe745b0f1619fb887ca"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:874317057a58a9c6ddf59fe1491e478217daa9fdb043a00358a15de4f62f9a2d"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:5d8eb7fe39e81dc1530a3ec81a35e69770839c76607c461eb9d0902427fab3e1"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:08f85d6674d804a493c3e9ec10a807f9bd8f482781487eda064913b537f99d7f"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-win32.whl", hash = "sha256:eadf8c4b24b63aef8810ed585c24ac1fc022ee771211772a6e9f78c63aa949ff"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:0e931539edeb9158ef83537cd571051f8a9608737642c20b088a37bd5d76c5c9"}, - {file = "rapidfuzz-3.9.1-cp311-cp311-win_arm64.whl", hash = "sha256:bcc0ffcaeb1e499e708f32ec30177ed690b3f25455c91ad8c2240986c69f9ebe"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:8781e45c56f7f3a64940f4d594a4ffd69360147925a706569b2b0c57347b2225"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0edc950c6a04c19db10670cd04e33403b3eb0f175deb620f9668595d378b1005"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0ceb0d7bdec910d93793d32633ba0cb644356cf6778f9d91b727da0075beaec1"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:4a231e8f3bae82f10e7188965b37c91d8bfb80136595c860c8a08eb0dd07764d"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9bfa8c0a8ce09b4bcd36322f8f375750dca160fbdbeb2e763a695cef3ae9133e"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1e872627d5359c840f3e431b0beb263518048917c3e076f624870552d84e7dc6"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7f006c3af82c478df09a790fb4846b5acd00a187d75715674d71f5dc0ac982ce"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:32718fa69306df969bf4fca1719f8900b83df315a2a8153942d5b8906f4fd1d6"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:a89b219c1a7933a0673b2dbb1ffe701057d82e5cb843552be4f55b61b557031e"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:b26cc9459e096959fab3a4a8a17b96a6c7c961f9db5c37c1c3c7a06789316cf7"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:2f9044a4470343087cde10beaa36266519d5da110a9a4597b43e6aa35fa928d3"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:a3a48fc6dc274b803a366a4baec99e212792ae1b1e73d42235b2042cd3ade7c1"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-win32.whl", hash = "sha256:b71e7f99ed048a338e4a1ac34f56b3b3933a3ba2dfbb04450c786a8ddd97f4db"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:e58489934d0147f1edda693cb983bea40f2b45ae6756fd47c1005b538f817a2f"}, - {file = "rapidfuzz-3.9.1-cp312-cp312-win_arm64.whl", hash = "sha256:829fbad93266fffa0f9d722a94cbb1b95b53e3c04be4e872193496a0cfbd66f0"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:bca2b93c75f87cd85832cdd5bb06b4b5642e2a05c8e3550841ddf5d564ce4abb"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:d3397630f22e6c60dda8be3e9dbcf6a341695d487df8a6c92f4a2f7ebcdaecf7"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:df7bba8d4a8fb8e7559a9e83dfc5385dc6fe89efd73e32d253667242faf1883c"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8e70605350cb6ec5091e06de62d3dcb058f694b059b4e1a9d85bfbf892f70030"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:678fcaa5117ddb6263160a7c5f33cc9ea3df335465f5d53715707fad103e1d09"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:08dcd347d408912b6da778a73a0d7a2adad7fe238a44263e5e3789f2a8d84669"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7149afaf0294882b6b15bb6fa9fc38ff1d761e50117460ee3561181c1c4e2230"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:0c568b89a5016e76f0b3f85e9379036da99c5e7ec26b33935453d353a1938b74"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:a079164675d24eb715230bf9dd252683ae3c9c0c0a236f0b8098630268b899e9"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:f6f4e8235d0acf1972f5eb4091c4a0473e5670a754f166c0c718ce21e945f879"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:ea62c82eb2c65bd49651e95f4f46874483ae4da1c3b57997e58f1b4fb2de6c05"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3ab6ad7e70469aed24e24378b19a9e47fc757c847399b22c612a0fccacc795cb"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-win32.whl", hash = "sha256:bf5184b17e26a82b00c7ee05d9ec5d826113df55830bbc447bf6d6e7469c70fb"}, - {file = "rapidfuzz-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:493354f50b9855271ac846b213e394e08446e70cef5cc033e5302a2220f3ae7b"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:c8b0e6640421e55d69e186ce7fb9e6c723cfd3b6f91beaeb28705c2a46c8a194"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:bc68fb8f2a8b5b3a4526b7a65e7d5c7f821882f56d9dcbcce4c6859a9e5bdcd7"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:77767b119ac05662d216a8cc4092ac28dbc015d9caabebdbefe371b0dd82a38e"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5dbcc4add07bd60ea73b94392fed28f83dba0fe796097da47627fd539bd6daca"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c0899de4fc1a7a36f14be556a0dacf40ea5c0fe22c6b45b2ea2674e1ac47e269"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e9f075366cee63a6b06bd7f9285eb9f1785382a6493afcb7054202e20508bf94"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:349e9c15092d20a1f6ff1795e068f39a9ee5e84c54b3addbc66d0ac469c4ef43"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a645f362dafc103dbe7f43a2ad34f76284773cd7d1b00514d1c591848a1c817f"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:03a0a4bc8d4bd3e6f882b4c2ac183825a9b6dabe7e5a97bb6a1075e4635c944d"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:fbce66cb2e331b0888c79b594eab76e2c609c2637050085daadff5325d471dc2"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e5d7b3154f6df9e05c2016de5e95f8cba4fe636a4e5520ebcd89bc6c54b8e4ed"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:aaba665f92c011c6f284e933ab02b5dc129a6d3f48fce913ec4a214bd530135e"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-win32.whl", hash = "sha256:61b343c581f4926260248069d8fdbbbf293c19c12ef440ad5ced15bcff277a84"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:ce3335324198e1388a1c4e50d40f45107367010afe9fa09fd46278160f0ab591"}, - {file = "rapidfuzz-3.9.1-cp39-cp39-win_arm64.whl", hash = "sha256:998977df2ae01ff8b7bc3b29a860b4a863005e0533e323df3fd555a31ef33f0e"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:dc4b5de5d6f9347d836d849b56bca630169353cbe5c10fa7fe93bb1677b49770"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:9f74d93148081049ccc86f276d54cd7c8c0692250245660b4fcd904ed1db1e01"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9f9dfdcd75e16e5874efee233b28aec1322623b0f1f20641452d06ea2d8ba5ef"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:97ab8f153984a5d827ebb5a5b80ee59563efcf2fa3e569dcd46ea7e7c9845e93"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8a6d5a8edc452920efdf1b499a2a47bb8a28440f7ab3fe28bb7d6636ccf71c3"}, - {file = "rapidfuzz-3.9.1-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:06879b598e798a4d33a283c2b4fa0d555d7706b6531e3321b161d62e986f7f57"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0f906ab6220778404498e0ce255c4cc89f98ea5e656e54cc59c5813c877eb86b"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:d3da444890c9559fd15717d97f8373b1cd14007f68c9b037aa93ef7ca969b559"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc4503841cd3cbe22b5ac44f15bc834ec97d811a3c3943f73f5643266c8674e1"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5713c56b30ed75ada3a8f008cf8e8e6323386ce48fac2bf2d07285fe6c91f5a4"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eb3f1af099cd1d98001691fbdadd422f088f21eadcacf5698b393b7569e24dc4"}, - {file = "rapidfuzz-3.9.1-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:53477e1e6d85d603c9a319cfd00ab9f0a57b6d68bcdb268d6b15a79e64d693d0"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:a47550eabf235e5d50e7d448c18f77f6e8082aa3571e9df511c8388525ea9372"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:c6b11a38b61cc2462a113b123f5e932cda0e525f816d6fe4b68516f97d7f9d49"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:414644a2fc8a3e5fafda95b430214ed892faa4d0a07401d33892bc9ca5c84974"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1539e7439b68013c5d2ab7ed9d3d221480a15595207764145ae177077d28016d"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e18f0e9351f7e5d5387774ff4d5cabd824341e16b866eb1c8d3f557111b447ef"}, - {file = "rapidfuzz-3.9.1-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:d2ff268a8bf57a76512804d5ca2097afaf98e64e8947d514cde7e2e8446aa5f7"}, - {file = "rapidfuzz-3.9.1.tar.gz", hash = "sha256:a42eb645241f39a59c45a7fc15e3faf61886bff3a4a22263fd0f7cfb90e91b7f"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c9b9793c19bdf38656c8eaefbcf4549d798572dadd70581379e666035c9df781"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:015b5080b999404fe06ec2cb4f40b0be62f0710c926ab41e82dfbc28e80675b4"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:acc5ceca9c1e1663f3e6c23fb89a311f69b7615a40ddd7645e3435bf3082688a"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1424e238bc3f20e1759db1e0afb48a988a9ece183724bef91ea2a291c0b92a95"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ed01378f605aa1f449bee82cd9c83772883120d6483e90aa6c5a4ce95dc5c3aa"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:eb26d412271e5a76cdee1c2d6bf9881310665d3fe43b882d0ed24edfcb891a84"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8f37e9e1f17be193c41a31c864ad4cd3ebd2b40780db11cd5c04abf2bcf4201b"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:d070ec5cf96b927c4dc5133c598c7ff6db3b833b363b2919b13417f1002560bc"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:10e61bb7bc807968cef09a0e32ce253711a2d450a4dce7841d21d45330ffdb24"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:31a2fc60bb2c7face4140010a7aeeafed18b4f9cdfa495cc644a68a8c60d1ff7"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:fbebf1791a71a2e89f5c12b78abddc018354d5859e305ec3372fdae14f80a826"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:aee9fc9e3bb488d040afc590c0a7904597bf4ccd50d1491c3f4a5e7e67e6cd2c"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-win32.whl", hash = "sha256:005a02688a51c7d2451a2d41c79d737aa326ff54167211b78a383fc2aace2c2c"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-win_amd64.whl", hash = "sha256:3a2e75e41ee3274754d3b2163cc6c82cd95b892a85ab031f57112e09da36455f"}, + {file = "rapidfuzz-3.9.4-cp310-cp310-win_arm64.whl", hash = "sha256:2c99d355f37f2b289e978e761f2f8efeedc2b14f4751d9ff7ee344a9a5ca98d9"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:07141aa6099e39d48637ce72a25b893fc1e433c50b3e837c75d8edf99e0c63e1"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:db1664eaff5d7d0f2542dd9c25d272478deaf2c8412e4ad93770e2e2d828e175"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bc01a223f6605737bec3202e94dcb1a449b6c76d46082cfc4aa980f2a60fd40e"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1869c42e73e2a8910b479be204fa736418741b63ea2325f9cc583c30f2ded41a"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:62ea7007941fb2795fff305ac858f3521ec694c829d5126e8f52a3e92ae75526"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:698e992436bf7f0afc750690c301215a36ff952a6dcd62882ec13b9a1ebf7a39"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b76f611935f15a209d3730c360c56b6df8911a9e81e6a38022efbfb96e433bab"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:129627d730db2e11f76169344a032f4e3883d34f20829419916df31d6d1338b1"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:90a82143c14e9a14b723a118c9ef8d1bbc0c5a16b1ac622a1e6c916caff44dd8"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:ded58612fe3b0e0d06e935eaeaf5a9fd27da8ba9ed3e2596307f40351923bf72"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:f16f5d1c4f02fab18366f2d703391fcdbd87c944ea10736ca1dc3d70d8bd2d8b"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:26aa7eece23e0df55fb75fbc2a8fb678322e07c77d1fd0e9540496e6e2b5f03e"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-win32.whl", hash = "sha256:f187a9c3b940ce1ee324710626daf72c05599946bd6748abe9e289f1daa9a077"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-win_amd64.whl", hash = "sha256:d8e9130fe5d7c9182990b366ad78fd632f744097e753e08ace573877d67c32f8"}, + {file = "rapidfuzz-3.9.4-cp311-cp311-win_arm64.whl", hash = "sha256:40419e98b10cd6a00ce26e4837a67362f658fc3cd7a71bd8bd25c99f7ee8fea5"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:b5d5072b548db1b313a07d62d88fe0b037bd2783c16607c647e01b070f6cf9e5"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cf5bcf22e1f0fd273354462631d443ef78d677f7d2fc292de2aec72ae1473e66"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0c8fc973adde8ed52810f590410e03fb6f0b541bbaeb04c38d77e63442b2df4c"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2464bb120f135293e9a712e342c43695d3d83168907df05f8c4ead1612310c7"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:8d9d58689aca22057cf1a5851677b8a3ccc9b535ca008c7ed06dc6e1899f7844"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:167e745f98baa0f3034c13583e6302fb69249a01239f1483d68c27abb841e0a1"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db0bf0663b4b6da1507869722420ea9356b6195aa907228d6201303e69837af9"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:cd6ac61b74fdb9e23f04d5f068e6cf554f47e77228ca28aa2347a6ca8903972f"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:60ff67c690acecf381759c16cb06c878328fe2361ddf77b25d0e434ea48a29da"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:cb934363380c60f3a57d14af94325125cd8cded9822611a9f78220444034e36e"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:fe833493fb5cc5682c823ea3e2f7066b07612ee8f61ecdf03e1268f262106cdd"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:2797fb847d89e04040d281cb1902cbeffbc4b5131a5c53fc0db490fd76b2a547"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-win32.whl", hash = "sha256:52e3d89377744dae68ed7c84ad0ddd3f5e891c82d48d26423b9e066fc835cc7c"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-win_amd64.whl", hash = "sha256:c76da20481c906e08400ee9be230f9e611d5931a33707d9df40337c2655c84b5"}, + {file = "rapidfuzz-3.9.4-cp312-cp312-win_arm64.whl", hash = "sha256:f2d2846f3980445864c7e8b8818a29707fcaff2f0261159ef6b7bd27ba139296"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:355fc4a268ffa07bab88d9adee173783ec8d20136059e028d2a9135c623c44e6"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:4d81a78f90269190b568a8353d4ea86015289c36d7e525cd4d43176c88eff429"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e618625ffc4660b26dc8e56225f8b966d5842fa190e70c60db6cd393e25b86e"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b712336ad6f2bacdbc9f1452556e8942269ef71f60a9e6883ef1726b52d9228a"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:84fc1ee19fdad05770c897e793836c002344524301501d71ef2e832847425707"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1950f8597890c0c707cb7e0416c62a1cf03dcdb0384bc0b2dbda7e05efe738ec"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a6c35f272ec9c430568dc8c1c30cb873f6bc96be2c79795e0bce6db4e0e101d"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:1df0f9e9239132a231c86ae4f545ec2b55409fa44470692fcfb36b1bd00157ad"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:d2c51955329bfccf99ae26f63d5928bf5be9fcfcd9f458f6847fd4b7e2b8986c"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:3c522f462d9fc504f2ea8d82e44aa580e60566acc754422c829ad75c752fbf8d"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:d8a52fc50ded60d81117d7647f262c529659fb21d23e14ebfd0b35efa4f1b83d"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:04dbdfb0f0bfd3f99cf1e9e24fadc6ded2736d7933f32f1151b0f2abb38f9a25"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-win32.whl", hash = "sha256:4968c8bd1df84b42f382549e6226710ad3476f976389839168db3e68fd373298"}, + {file = "rapidfuzz-3.9.4-cp38-cp38-win_amd64.whl", hash = "sha256:3fe4545f89f8d6c27b6bbbabfe40839624873c08bd6700f63ac36970a179f8f5"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:9f256c8fb8f3125574c8c0c919ab0a1f75d7cba4d053dda2e762dcc36357969d"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f5fdc09cf6e9d8eac3ce48a4615b3a3ee332ea84ac9657dbbefef913b13e632f"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d395d46b80063d3b5d13c0af43d2c2cedf3ab48c6a0c2aeec715aa5455b0c632"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7fa714fb96ce9e70c37e64c83b62fe8307030081a0bfae74a76fac7ba0f91715"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1bc1a0f29f9119be7a8d3c720f1d2068317ae532e39e4f7f948607c3a6de8396"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6022674aa1747d6300f699cd7c54d7dae89bfe1f84556de699c4ac5df0838082"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dcb72e5f9762fd469701a7e12e94b924af9004954f8c739f925cb19c00862e38"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:ad04ae301129f0eb5b350a333accd375ce155a0c1cec85ab0ec01f770214e2e4"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:f46a22506f17c0433e349f2d1dc11907c393d9b3601b91d4e334fa9a439a6a4d"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:01b42a8728c36011718da409aa86b84984396bf0ca3bfb6e62624f2014f6022c"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:e590d5d5443cf56f83a51d3c4867bd1f6be8ef8cfcc44279522bcef3845b2a51"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:4c72078b5fdce34ba5753f9299ae304e282420e6455e043ad08e4488ca13a2b0"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-win32.whl", hash = "sha256:f75639277304e9b75e6a7b3c07042d2264e16740a11e449645689ed28e9c2124"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-win_amd64.whl", hash = "sha256:e81e27e8c32a1e1278a4bb1ce31401bfaa8c2cc697a053b985a6f8d013df83ec"}, + {file = "rapidfuzz-3.9.4-cp39-cp39-win_arm64.whl", hash = "sha256:15bc397ee9a3ed1210b629b9f5f1da809244adc51ce620c504138c6e7095b7bd"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-macosx_10_15_x86_64.whl", hash = "sha256:20488ade4e1ddba3cfad04f400da7a9c1b91eff5b7bd3d1c50b385d78b587f4f"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:e61b03509b1a6eb31bc5582694f6df837d340535da7eba7bedb8ae42a2fcd0b9"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:098d231d4e51644d421a641f4a5f2f151f856f53c252b03516e01389b2bfef99"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:17ab8b7d10fde8dd763ad428aa961c0f30a1b44426e675186af8903b5d134fb0"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e272df61bee0a056a3daf99f9b1bd82cf73ace7d668894788139c868fdf37d6f"}, + {file = "rapidfuzz-3.9.4-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:d6481e099ff8c4edda85b8b9b5174c200540fd23c8f38120016c765a86fa01f5"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:ad61676e9bdae677d577fe80ec1c2cea1d150c86be647e652551dcfe505b1113"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:af65020c0dd48d0d8ae405e7e69b9d8ae306eb9b6249ca8bf511a13f465fad85"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4d38b4e026fcd580e0bda6c0ae941e0e9a52c6bc66cdce0b8b0da61e1959f5f8"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f74ed072c2b9dc6743fb19994319d443a4330b0e64aeba0aa9105406c7c5b9c2"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aee5f6b8321f90615c184bd8a4c676e9becda69b8e4e451a90923db719d6857c"}, + {file = "rapidfuzz-3.9.4-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:3a555e3c841d6efa350f862204bb0a3fea0c006b8acc9b152b374fa36518a1c6"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-macosx_10_15_x86_64.whl", hash = "sha256:0772150d37bf018110351c01d032bf9ab25127b966a29830faa8ad69b7e2f651"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:addcdd3c3deef1bd54075bd7aba0a6ea9f1d01764a08620074b7a7b1e5447cb9"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3fe86b82b776554add8f900b6af202b74eb5efe8f25acdb8680a5c977608727f"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b0fc91ac59f4414d8542454dfd6287a154b8e6f1256718c898f695bdbb993467"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3a944e546a296a5fdcaabb537b01459f1b14d66f74e584cb2a91448bffadc3c1"}, + {file = "rapidfuzz-3.9.4-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:4fb96ba96d58c668a17a06b5b5e8340fedc26188e87b0d229d38104556f30cd8"}, + {file = "rapidfuzz-3.9.4.tar.gz", hash = "sha256:366bf8947b84e37f2f4cf31aaf5f37c39f620d8c0eddb8b633e6ba0129ca4a0a"}, ] [package.extras] @@ -3559,13 +3519,13 @@ files = [ [[package]] name = "requests" -version = "2.32.2" +version = "2.32.3" description = "Python HTTP for Humans." optional = false python-versions = ">=3.8" files = [ - {file = "requests-2.32.2-py3-none-any.whl", hash = "sha256:fc06670dd0ed212426dfeb94fc1b983d917c4f9847c863f313c9dfaaffb7c23c"}, - {file = "requests-2.32.2.tar.gz", hash = "sha256:dd951ff5ecf3e3b3aa26b40703ba77495dab41da839ae72ef3c8e5d8e2433289"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -3613,13 +3573,13 @@ jupyter = ["ipywidgets (>=7.5.1,<9)"] [[package]] name = "rich-click" -version = "1.8.2" +version = "1.8.3" description = "Format click help output nicely with rich" optional = false python-versions = ">=3.7" files = [ - {file = "rich_click-1.8.2-py3-none-any.whl", hash = "sha256:b57856f304e4fe0394b82d7ce0784450758f8c8b4e201ccc4320501cc201806b"}, - {file = "rich_click-1.8.2.tar.gz", hash = "sha256:8e29bdede858b59aa2859a1ab1c4ccbd39ed7ed5870262dae756fba6b5dc72e8"}, + {file = "rich_click-1.8.3-py3-none-any.whl", hash = "sha256:636d9c040d31c5eee242201b5bf4f2d358bfae4db14bb22ec1cafa717cfd02cd"}, + {file = "rich_click-1.8.3.tar.gz", hash = "sha256:6d75bdfa7aa9ed2c467789a0688bc6da23fbe3a143e19aa6ad3f8bac113d2ab3"}, ] [package.dependencies] @@ -3633,13 +3593,13 @@ docs = ["markdown-include", "mkdocs", "mkdocs-glightbox", "mkdocs-material-exten [[package]] name = "sanic" -version = "23.12.1" +version = "24.6.0" description = "A web server and web framework that's written to go fast. Build fast. Run fast." optional = false python-versions = ">=3.8" files = [ - {file = "sanic-23.12.1-py3-none-any.whl", hash = "sha256:e292293b2663a7afeb380bdc48ab93978468b27deae46ad9561513941eb0311f"}, - {file = "sanic-23.12.1.tar.gz", hash = "sha256:2528ca81d2bdc58ea67d93c500df1a9c58404904b0bc3442425b464c72b4bb84"}, + {file = "sanic-24.6.0-py3-none-any.whl", hash = "sha256:e2c6b392e213d85d9843cf27c64e3f2dacb3ec5c31c8c7ade4c404cd3030e994"}, + {file = "sanic-24.6.0.tar.gz", hash = "sha256:2e0841e2c8c28e68a0e6fc570c42aafbbe3b385d7141b9f96997d9d6c17d7afb"}, ] [package.dependencies] @@ -3648,6 +3608,7 @@ html5tagger = ">=1.2.1" httptools = ">=0.0.10" multidict = ">=5.0,<7.0" sanic-routing = ">=23.12.0" +setuptools = ">=70.1.0" tracerite = ">=1.0.0" typing-extensions = ">=4.4.0" ujson = {version = ">=1.35", markers = "sys_platform != \"win32\" and implementation_name == \"cpython\""} @@ -3655,12 +3616,12 @@ uvloop = {version = ">=0.15.0", markers = "sys_platform != \"win32\" and impleme websockets = ">=10.0" [package.extras] -all = ["autodocsumm (>=0.2.11)", "bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "cryptography", "docutils", "enum-tools[sphinx]", "m2r2", "mistune (<2.0.0)", "mypy", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "sphinx (>=2.1.2)", "sphinx-rtd-theme (>=0.4.3)", "towncrier", "tox", "types-ujson", "uvicorn (<0.15.0)"] -dev = ["bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "cryptography", "docutils", "mypy", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "towncrier", "tox", "types-ujson", "uvicorn (<0.15.0)"] +all = ["autodocsumm (>=0.2.11)", "bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "cryptography", "docutils", "enum-tools[sphinx]", "m2r2", "mistune (<2.0.0)", "mypy", "pygments", "pytest (>=8.2.2)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "sphinx (>=2.1.2)", "sphinx-rtd-theme (>=0.4.3)", "towncrier", "tox", "types-ujson", "uvicorn"] +dev = ["bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "cryptography", "docutils", "mypy", "pygments", "pytest (>=8.2.2)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "towncrier", "tox", "types-ujson", "uvicorn"] docs = ["autodocsumm (>=0.2.11)", "docutils", "enum-tools[sphinx]", "m2r2", "mistune (<2.0.0)", "pygments", "sphinx (>=2.1.2)", "sphinx-rtd-theme (>=0.4.3)"] ext = ["sanic-ext"] http3 = ["aioquic"] -test = ["bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "docutils", "mypy", "pygments", "pytest (==7.1.*)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "types-ujson", "uvicorn (<0.15.0)"] +test = ["bandit", "beautifulsoup4", "chardet (==3.*)", "coverage", "docutils", "mypy", "pygments", "pytest (>=8.2.2)", "pytest-benchmark", "pytest-sanic", "ruff", "sanic-testing (>=23.6.0)", "slotscheck (>=0.8.0,<1)", "types-ujson", "uvicorn"] [[package]] name = "sanic-routing" @@ -3778,18 +3739,18 @@ tests = ["coverage[toml] (>=5.0.2)", "pytest"] [[package]] name = "setuptools" -version = "70.0.0" +version = "70.3.0" description = "Easily download, build, install, upgrade, and uninstall Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "setuptools-70.0.0-py3-none-any.whl", hash = "sha256:54faa7f2e8d2d11bcd2c07bed282eef1046b5c080d1c32add737d7b5817b1ad4"}, - {file = "setuptools-70.0.0.tar.gz", hash = "sha256:f211a66637b8fa059bb28183da127d4e86396c991a942b028c6650d4319c3fd0"}, + {file = "setuptools-70.3.0-py3-none-any.whl", hash = "sha256:fe384da74336c398e0d956d1cae0669bc02eed936cdb1d49b57de1990dc11ffc"}, + {file = "setuptools-70.3.0.tar.gz", hash = "sha256:f171bab1dfbc86b132997f26a119f6056a57950d058587841a0082e8830f9dc5"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] -testing = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.1)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.2.1)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "pyproject-hooks (!=1.1)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-favicon", "sphinx-inline-tabs", "sphinx-lint", "sphinx-notfound-page (>=1,<2)", "sphinx-reredirects", "sphinxcontrib-towncrier"] +test = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.14)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "jaraco.test", "mypy (==1.10.0)", "packaging (>=23.2)", "pip (>=19.1)", "pyproject-hooks (!=1.1)", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-home (>=0.5)", "pytest-mypy", "pytest-perf", "pytest-ruff (>=0.3.2)", "pytest-subprocess", "pytest-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] [[package]] name = "shellingham" @@ -3826,13 +3787,13 @@ files = [ [[package]] name = "sqlparse" -version = "0.5.0" +version = "0.5.1" description = "A non-validating SQL parser." optional = false python-versions = ">=3.8" files = [ - {file = "sqlparse-0.5.0-py3-none-any.whl", hash = "sha256:c204494cd97479d0e39f28c93d46c0b2d5959c7b9ab904762ea6c7af211c8663"}, - {file = "sqlparse-0.5.0.tar.gz", hash = "sha256:714d0a4932c059d16189f58ef5411ec2287a4360f17cdd0edd2d09d4c5087c93"}, + {file = "sqlparse-0.5.1-py3-none-any.whl", hash = "sha256:773dcbf9a5ab44a090f3441e2180efe2560220203dc2f8c0b0fa141e18b505e4"}, + {file = "sqlparse-0.5.1.tar.gz", hash = "sha256:bb6b4df465655ef332548e24f08e205afc81b9ab86cb1c45657a7ff173a3a00e"}, ] [package.extras] @@ -3934,13 +3895,13 @@ files = [ [[package]] name = "tomlkit" -version = "0.12.5" +version = "0.13.0" description = "Style preserving TOML library" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tomlkit-0.12.5-py3-none-any.whl", hash = "sha256:af914f5a9c59ed9d0762c7b64d3b5d5df007448eb9cd2edc8a46b1eafead172f"}, - {file = "tomlkit-0.12.5.tar.gz", hash = "sha256:eef34fba39834d4d6b73c9ba7f3e4d1c417a4e56f89a7e96e090dd0d24b8fb3c"}, + {file = "tomlkit-0.13.0-py3-none-any.whl", hash = "sha256:7075d3042d03b80f603482d69bf0c8f345c2b30e41699fd8883227f89972b264"}, + {file = "tomlkit-0.13.0.tar.gz", hash = "sha256:08ad192699734149f5b97b45f1f18dad7eb1b6d16bc72ad0c2335772650d7b72"}, ] [[package]] @@ -3959,13 +3920,13 @@ html5tagger = ">=1.2.1" [[package]] name = "trove-classifiers" -version = "2024.5.22" +version = "2024.7.2" description = "Canonical source for classifiers on PyPI (pypi.org)." optional = false python-versions = "*" files = [ - {file = "trove_classifiers-2024.5.22-py3-none-any.whl", hash = "sha256:c43ade18704823e4afa3d9db7083294bc4708a5e02afbcefacd0e9d03a7a24ef"}, - {file = "trove_classifiers-2024.5.22.tar.gz", hash = "sha256:8a6242bbb5c9ae88d34cf665e816b287d2212973c8777dfaef5ec18d72ac1d03"}, + {file = "trove_classifiers-2024.7.2-py3-none-any.whl", hash = "sha256:ccc57a33717644df4daca018e7ec3ef57a835c48e96a1e71fc07eb7edac67af6"}, + {file = "trove_classifiers-2024.7.2.tar.gz", hash = "sha256:8328f2ac2ce3fd773cbb37c765a0ed7a83f89dc564c7d452f039b69249d0ac35"}, ] [[package]] @@ -4070,13 +4031,13 @@ typing-extensions = ">=3.7.4.3" [[package]] name = "types-aiofiles" -version = "23.2.0.20240403" +version = "24.1.0.20240626" description = "Typing stubs for aiofiles" optional = false python-versions = ">=3.8" files = [ - {file = "types-aiofiles-23.2.0.20240403.tar.gz", hash = "sha256:1ffcf8f5f72b81f71139f754ea2610ab0017f27ba4fd771e187b07840ee49c0f"}, - {file = "types_aiofiles-23.2.0.20240403-py3-none-any.whl", hash = "sha256:adeeb4b999f19fda2dfe91c07857ff54701b6ee9b227b523a5a7be92125a2c5f"}, + {file = "types-aiofiles-24.1.0.20240626.tar.gz", hash = "sha256:48604663e24bc2d5038eac05ccc33e75799b0779e93e13d6a8f711ddc306ac08"}, + {file = "types_aiofiles-24.1.0.20240626-py3-none-any.whl", hash = "sha256:7939eca4a8b4f9c6491b6e8ef160caee9a21d32e18534a57d5ed90aee47c66b4"}, ] [[package]] @@ -4169,13 +4130,13 @@ files = [ [[package]] name = "typing-extensions" -version = "4.12.0" +version = "4.12.2" description = "Backported and Experimental Type Hints for Python 3.8+" optional = false python-versions = ">=3.8" files = [ - {file = "typing_extensions-4.12.0-py3-none-any.whl", hash = "sha256:b349c66bea9016ac22978d800cfff206d5f9816951f12a7d0ec5578b0a819594"}, - {file = "typing_extensions-4.12.0.tar.gz", hash = "sha256:8cbcdc8606ebcb0d95453ad7dc5065e6237b6aa230a31e81d0f440c30fed5fd8"}, + {file = "typing_extensions-4.12.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, ] [[package]] @@ -4293,13 +4254,13 @@ files = [ [[package]] name = "urllib3" -version = "1.26.18" +version = "1.26.19" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false -python-versions = ">=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*, !=3.4.*, !=3.5.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,>=2.7" files = [ - {file = "urllib3-1.26.18-py2.py3-none-any.whl", hash = "sha256:34b97092d7e0a3a8cf7cd10e386f401b3737364026c45e622aa02903dffe0f07"}, - {file = "urllib3-1.26.18.tar.gz", hash = "sha256:f8ecc1bba5667413457c529ab955bf8c67b45db799d159066261719e328580a0"}, + {file = "urllib3-1.26.19-py2.py3-none-any.whl", hash = "sha256:37a0344459b199fce0e80b0d3569837ec6b6937435c5244e7fd73fa6006830f3"}, + {file = "urllib3-1.26.19.tar.gz", hash = "sha256:3e3d753a8618b86d7de333b4223005f68720bcd6a7d2bcb9fbd2229ec7c1e429"}, ] [package.extras] @@ -4309,13 +4270,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "uvicorn" -version = "0.29.0" +version = "0.30.1" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.29.0-py3-none-any.whl", hash = "sha256:2c2aac7ff4f4365c206fd773a39bf4ebd1047c238f8b8268ad996829323473de"}, - {file = "uvicorn-0.29.0.tar.gz", hash = "sha256:6a69214c0b6a087462412670b3ef21224fa48cae0e452b5883e8e8bdfdd11dd0"}, + {file = "uvicorn-0.30.1-py3-none-any.whl", hash = "sha256:cd17daa7f3b9d7a24de3617820e634d0933b69eed8e33a516071174427238c81"}, + {file = "uvicorn-0.30.1.tar.gz", hash = "sha256:d46cd8e0fd80240baffbcd9ec1012a712938754afcf81bce56c024c1656aece8"}, ] [package.dependencies] @@ -4379,13 +4340,13 @@ test = ["Cython (>=0.29.36,<0.30.0)", "aiohttp (==3.9.0b0)", "aiohttp (>=3.8.1)" [[package]] name = "virtualenv" -version = "20.26.2" +version = "20.26.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.2-py3-none-any.whl", hash = "sha256:a624db5e94f01ad993d476b9ee5346fdf7b9de43ccaee0e0197012dc838a0e9b"}, - {file = "virtualenv-20.26.2.tar.gz", hash = "sha256:82bf0f4eebbb78d36ddaee0283d43fe5736b53880b8a8cdcd37390a07ac3741c"}, + {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, + {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, ] [package.dependencies] @@ -4889,18 +4850,18 @@ multidict = ">=4.0" [[package]] name = "zipp" -version = "3.19.0" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.19.0-py3-none-any.whl", hash = "sha256:96dc6ad62f1441bcaccef23b274ec471518daf4fbbc580341204936a5a3dddec"}, - {file = "zipp-3.19.0.tar.gz", hash = "sha256:952df858fb3164426c976d9338d3961e8e8b3758e2e059e0f754b8c4262625ee"}, + {file = "zipp-3.19.2-py3-none-any.whl", hash = "sha256:f091755f667055f2d02b32c53771a7a6c8b47e1fdbc4b72a8b9072b3eef8015c"}, + {file = "zipp-3.19.2.tar.gz", hash = "sha256:bf1dcf6450f873a13e952a29504887c89e6de7506209e5b1bcc3460135d4de19"}, ] [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] -testing = ["big-O", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] +doc = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", "jaraco.test", "more-itertools", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-ignore-flaky", "pytest-mypy", "pytest-ruff (>=0.2.1)"] [[package]] name = "zope-interface" @@ -4977,4 +4938,4 @@ starlite = ["starlite"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "a2474ada3f0efde97f74d21d05fc1b062de033f9fbf8ba6ba194015813c2f27a" +content-hash = "8df114664279596351305c9192ca2a58146a80814c9a91ee998e97ceb14316c9" diff --git a/pyproject.toml b/pyproject.toml index ebf901df80..58bdb8d7ff 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,7 +68,7 @@ asgiref = "^3.2" ddtrace = ">=1.6.4" email-validator = {version = ">=1.1.3,<3.0.0", optional = false} freezegun = "^1.2.1" -libcst = {version = ">=0.4.7", optional = false} +libcst = {version = ">=1.0.0", optional = false} MarkupSafe = "2.1.3" nox = "^2023.4.22" nox-poetry = "^1.0.3" @@ -235,9 +235,6 @@ ignore = [ "S102", "S104", "S324", - # maybe we can enable this in future - # we'd want to have consistent docstrings in future - "D", "ANN101", # missing annotation for self? # definitely enable these, maybe not in tests "ANN102", @@ -351,6 +348,17 @@ ignore = [ "FIX001", "FIX002", "FA100", + + # Docstrings, maybe to enable later + "D100", + "D101", + "D102", + "D103", + "D104", + "D105", + "D106", + "D107", + "D412", ] [tool.ruff.lint.per-file-ignores] @@ -370,6 +378,7 @@ ignore = [ "S603", "S607", "B018", + "D", ] "strawberry/extensions/tracing/__init__.py" = ["TCH004"] "tests/http/clients/__init__.py" = ["F401"] @@ -384,3 +393,6 @@ exclude =[ 'tests/codegen/snapshots/', 'tests/cli/snapshots/' ] + +[tool.ruff.lint.pydocstyle] +convention = "google" diff --git a/strawberry/__init__.py b/strawberry/__init__.py index 18b422a0d4..2cbda32b2f 100644 --- a/strawberry/__init__.py +++ b/strawberry/__init__.py @@ -1,22 +1,28 @@ +"""Strawberry is a Python library for GraphQL. + +Strawberry is a Python library for GraphQL that aims to stay close to the GraphQL +specification and allow for a more natural way of defining GraphQL schemas. +""" + from . import experimental, federation, relay -from .arguments import argument -from .auto import auto -from .custom_scalar import scalar from .directive import directive, directive_field -from .enum import enum, enum_value -from .field import field -from .lazy_type import LazyType, lazy -from .mutation import mutation, subscription -from .object_type import asdict, input, interface, type from .parent import Parent from .permission import BasePermission -from .private import Private from .scalars import ID from .schema import Schema from .schema_directive import schema_directive +from .types.arguments import argument +from .types.auto import auto +from .types.enum import enum, enum_value +from .types.field import field from .types.info import Info -from .union import union -from .unset import UNSET +from .types.lazy_type import LazyType, lazy +from .types.mutation import mutation, subscription +from .types.object_type import asdict, input, interface, type +from .types.private import Private +from .types.scalar import scalar +from .types.union import union +from .types.unset import UNSET __all__ = [ "BasePermission", diff --git a/strawberry/aiohttp/handlers/graphql_transport_ws_handler.py b/strawberry/aiohttp/handlers/graphql_transport_ws_handler.py index 80ccad9a59..52350199f7 100644 --- a/strawberry/aiohttp/handlers/graphql_transport_ws_handler.py +++ b/strawberry/aiohttp/handlers/graphql_transport_ws_handler.py @@ -57,3 +57,6 @@ async def handle_request(self) -> web.StreamResponse: await self.shutdown() return self._ws + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/aiohttp/handlers/graphql_ws_handler.py b/strawberry/aiohttp/handlers/graphql_ws_handler.py index 90db25bac5..a8a80e481c 100644 --- a/strawberry/aiohttp/handlers/graphql_ws_handler.py +++ b/strawberry/aiohttp/handlers/graphql_ws_handler.py @@ -60,3 +60,6 @@ async def handle_request(self) -> Any: await self.cleanup_operation(operation_id) return self._ws + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/aiohttp/test/client.py b/strawberry/aiohttp/test/client.py index 4b7f860cfc..6f30b7e7aa 100644 --- a/strawberry/aiohttp/test/client.py +++ b/strawberry/aiohttp/test/client.py @@ -48,3 +48,6 @@ async def request( ) return response + + +__all__ = ["GraphQLTestClient"] diff --git a/strawberry/aiohttp/views.py b/strawberry/aiohttp/views.py index 00ded62d5f..575107067d 100644 --- a/strawberry/aiohttp/views.py +++ b/strawberry/aiohttp/views.py @@ -177,3 +177,6 @@ def create_response( sub_response.content_type = "application/json" return sub_response + + +__all__ = ["GraphQLView"] diff --git a/strawberry/annotation.py b/strawberry/annotation.py index d39fe5a62a..86d06d73e5 100644 --- a/strawberry/annotation.py +++ b/strawberry/annotation.py @@ -20,26 +20,26 @@ ) from typing_extensions import Annotated, Self, get_args, get_origin -from strawberry.custom_scalar import ScalarDefinition -from strawberry.enum import EnumDefinition from strawberry.exceptions.not_a_strawberry_enum import NotAStrawberryEnumError -from strawberry.lazy_type import LazyType -from strawberry.private import is_private -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, + StrawberryObjectDefinition, StrawberryOptional, StrawberryTypeVar, get_object_definition, has_object_definition, ) -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.unset import UNSET +from strawberry.types.enum import EnumDefinition +from strawberry.types.lazy_type import LazyType +from strawberry.types.private import is_private +from strawberry.types.scalar import ScalarDefinition +from strawberry.types.unset import UNSET from strawberry.utils.typing import eval_type, is_generic, is_type_var if TYPE_CHECKING: - from strawberry.field import StrawberryField - from strawberry.type import StrawberryType - from strawberry.union import StrawberryUnion + from strawberry.types.base import StrawberryType + from strawberry.types.field import StrawberryField + from strawberry.types.union import StrawberryUnion ASYNC_TYPES = ( @@ -226,7 +226,7 @@ def create_type_var(self, evaled_type: TypeVar) -> StrawberryTypeVar: def create_union(self, evaled_type: Type[Any], args: list[Any]) -> StrawberryUnion: # Prevent import cycles - from strawberry.union import StrawberryUnion + from strawberry.types.union import StrawberryUnion # TODO: Deal with Forward References/origin if isinstance(evaled_type, StrawberryUnion): @@ -290,8 +290,7 @@ def _is_lazy_type(cls, annotation: Any) -> bool: @classmethod def _is_optional(cls, annotation: Any, args: List[Any]) -> bool: - """Returns True if the annotation is Optional[SomeType]""" - + """Returns True if the annotation is Optional[SomeType].""" # Optionals are represented as unions if not cls._is_union(annotation, args): return False @@ -303,8 +302,7 @@ def _is_optional(cls, annotation: Any, args: List[Any]) -> bool: @classmethod def _is_list(cls, annotation: Any) -> bool: - """Returns True if annotation is a List""" - + """Returns True if annotation is a List.""" annotation_origin = get_origin(annotation) annotation_mro = getattr(annotation, "__mro__", []) is_list = any(x is list for x in annotation_mro) @@ -318,7 +316,7 @@ def _is_list(cls, annotation: Any) -> bool: @classmethod def _is_strawberry_type(cls, evaled_type: Any) -> bool: # Prevent import cycles - from strawberry.union import StrawberryUnion + from strawberry.types.union import StrawberryUnion if isinstance(evaled_type, EnumDefinition): return True @@ -344,8 +342,7 @@ def _is_strawberry_type(cls, evaled_type: Any) -> bool: @classmethod def _is_union(cls, annotation: Any, args: List[Any]) -> bool: - """Returns True if annotation is a Union""" - + """Returns True if annotation is a Union.""" # this check is needed because unions declared with the new syntax `A | B` # don't have a `__origin__` property on them, but they are instances of # `UnionType`, which is only available in Python 3.10+ @@ -363,7 +360,7 @@ def _is_union(cls, annotation: Any, args: List[Any]) -> bool: if annotation_origin is typing.Union: return True - from strawberry.union import StrawberryUnion + from strawberry.types.union import StrawberryUnion return any(isinstance(arg, StrawberryUnion) for arg in args) @@ -386,3 +383,6 @@ def _is_input_type(type_: Any) -> bool: return False return type_.__strawberry_definition__.is_input + + +__all__ = ["StrawberryAnnotation"] diff --git a/strawberry/asgi/__init__.py b/strawberry/asgi/__init__.py index e73eefc3ea..c3c01cb9b4 100644 --- a/strawberry/asgi/__init__.py +++ b/strawberry/asgi/__init__.py @@ -117,12 +117,12 @@ def __init__( else: self.graphql_ide = graphql_ide - async def __call__(self, scope: Scope, receive: Receive, send: Send) -> None: + async def __call__(self, scope: Request, receive: Receive, send: Send) -> None: if scope["type"] == "http": - return await self.handle_http(scope, receive, send) + return await self.handle_http(scope, receive, send) # type: ignore elif scope["type"] == "websocket": - ws = WebSocket(scope=scope, receive=receive, send=send) + ws = WebSocket(scope, receive=receive, send=send) # type: ignore preferred_protocol = self.pick_preferred_protocol(ws) if preferred_protocol == GRAPHQL_TRANSPORT_WS_PROTOCOL: diff --git a/strawberry/asgi/handlers/graphql_transport_ws_handler.py b/strawberry/asgi/handlers/graphql_transport_ws_handler.py index ddb5f8986b..7cec132ffd 100644 --- a/strawberry/asgi/handlers/graphql_transport_ws_handler.py +++ b/strawberry/asgi/handlers/graphql_transport_ws_handler.py @@ -61,3 +61,6 @@ async def handle_request(self) -> None: pass finally: await self.shutdown() + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/asgi/handlers/graphql_ws_handler.py b/strawberry/asgi/handlers/graphql_ws_handler.py index a8441112ce..5ef966f63b 100644 --- a/strawberry/asgi/handlers/graphql_ws_handler.py +++ b/strawberry/asgi/handlers/graphql_ws_handler.py @@ -65,3 +65,6 @@ async def handle_request(self) -> Any: for operation_id in list(self.subscriptions.keys()): await self.cleanup_operation(operation_id) + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/asgi/test/client.py b/strawberry/asgi/test/client.py index 2494b6e1c0..74afd78229 100644 --- a/strawberry/asgi/test/client.py +++ b/strawberry/asgi/test/client.py @@ -48,3 +48,6 @@ def request( def _decode(self, response: Any, type: Literal["multipart", "json"]) -> Any: return response.json() + + +__all__ = ["GraphQLTestClient"] diff --git a/strawberry/chalice/views.py b/strawberry/chalice/views.py index c3b46864eb..3da2838eaa 100644 --- a/strawberry/chalice/views.py +++ b/strawberry/chalice/views.py @@ -94,10 +94,16 @@ def error_response( http_status_code: int, headers: Optional[Dict[str, str | List[str]]] = None, ) -> Response: - """ - A wrapper for error responses + """A wrapper for error responses. + + Args: + message: The error message. + error_code: The error code. + http_status_code: The HTTP status code. + headers: The headers to include in the response. + Returns: - An errors response + An errors response. """ body = {"Code": error_code, "Message": message} @@ -139,3 +145,6 @@ def execute_request(self, request: Request) -> Response: message=e.reason, http_status_code=e.status_code, ) + + +__all__ = ["GraphQLView"] diff --git a/strawberry/channels/handlers/__init__.py b/strawberry/channels/handlers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strawberry/channels/handlers/base.py b/strawberry/channels/handlers/base.py index 93998922cf..ec2ffe6b2c 100644 --- a/strawberry/channels/handlers/base.py +++ b/strawberry/channels/handlers/base.py @@ -92,7 +92,7 @@ async def channel_listen( Utility to listen for channels messages for this consumer inside a resolver (usually inside a subscription). - Parameters: + Args: type: The type of the message to wait for. timeout: @@ -104,7 +104,6 @@ async def channel_listen( execution and then discarded using `self.channel_layer.group_discard` at the end of the execution. """ - warnings.warn("Use listen_to_channel instead", DeprecationWarning, stacklevel=2) if self.channel_layer is None: raise RuntimeError( @@ -152,7 +151,7 @@ async def listen_to_channel( Utility to listen for channels messages for this consumer inside a resolver (usually inside a subscription). - Parameters: + Args: type: The type of the message to wait for. timeout: @@ -164,7 +163,6 @@ async def listen_to_channel( execution and then discarded using `self.channel_layer.group_discard` at the end of the execution. """ - # Code to acquire resource (Channels subscriptions) if self.channel_layer is None: raise RuntimeError( @@ -201,7 +199,6 @@ async def _listen_to_channel_generator( Seperated to allow user code to be run after subscribing to channels and before blocking to wait for incoming channel messages. """ - while True: awaitable = queue.get() if timeout is not None: @@ -215,3 +212,6 @@ async def _listen_to_channel_generator( class ChannelsWSConsumer(ChannelsConsumer, AsyncJsonWebsocketConsumer): """Base channels websocket async consumer.""" + + +__all__ = ["ChannelsConsumer", "ChannelsWSConsumer"] diff --git a/strawberry/channels/handlers/graphql_transport_ws_handler.py b/strawberry/channels/handlers/graphql_transport_ws_handler.py index a4fa1a0d6d..db290f4ef8 100644 --- a/strawberry/channels/handlers/graphql_transport_ws_handler.py +++ b/strawberry/channels/handlers/graphql_transport_ws_handler.py @@ -57,3 +57,6 @@ async def handle_request(self) -> Any: async def handle_disconnect(self, code: int) -> None: await self.shutdown() + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/channels/handlers/graphql_ws_handler.py b/strawberry/channels/handlers/graphql_ws_handler.py index 7ed6b3cb49..41ed4dc6ea 100644 --- a/strawberry/channels/handlers/graphql_ws_handler.py +++ b/strawberry/channels/handlers/graphql_ws_handler.py @@ -67,3 +67,6 @@ async def handle_invalid_message(self, error_message: str) -> None: # channels integration is a high level wrapper that forwards this to # both us and the BaseGraphQLTransportWSHandler. pass + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/channels/handlers/http_handler.py b/strawberry/channels/handlers/http_handler.py index 67bd98eb55..2788b5d921 100644 --- a/strawberry/channels/handlers/http_handler.py +++ b/strawberry/channels/handlers/http_handler.py @@ -1,4 +1,4 @@ -"""GraphQLHTTPHandler +"""GraphQLHTTPHandler. A consumer to provide a graphql endpoint, and optionally graphiql. """ @@ -25,7 +25,7 @@ from strawberry.http.temporal_response import TemporalResponse from strawberry.http.types import FormData from strawberry.http.typevars import Context, RootValue -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET from .base import ChannelsConsumer @@ -304,3 +304,6 @@ def run( root_value: Optional[RootValue] = UNSET, ) -> ChannelsResponse: return super().run(request, context, root_value) + + +__all__ = ["GraphQLHTTPConsumer", "SyncGraphQLHTTPConsumer"] diff --git a/strawberry/channels/handlers/ws_handler.py b/strawberry/channels/handlers/ws_handler.py index f5fa206273..7f7929b3f3 100644 --- a/strawberry/channels/handlers/ws_handler.py +++ b/strawberry/channels/handlers/ws_handler.py @@ -15,7 +15,7 @@ class GraphQLWSConsumer(ChannelsWSConsumer): - """A channels websocket consumer for GraphQL + """A channels websocket consumer for GraphQL. This handles the connections, then hands off to the appropriate handler based on the subprotocol. @@ -126,3 +126,6 @@ async def get_context( "connection_params": connection_params, "ws": request, } # type: ignore + + +__all__ = ["GraphQLWSConsumer"] diff --git a/strawberry/channels/router.py b/strawberry/channels/router.py index adf774c026..414902cd40 100644 --- a/strawberry/channels/router.py +++ b/strawberry/channels/router.py @@ -1,4 +1,4 @@ -"""GraphQLWebSocketRouter +"""GraphQLWebSocketRouter. This is a simple router class that might be better placed as part of Channels itself. It's a simple "SubProtocolRouter" that selects the websocket subprotocol based @@ -21,11 +21,12 @@ class GraphQLProtocolTypeRouter(ProtocolTypeRouter): - """ - Convenience class to set up GraphQL on both HTTP and Websocket, optionally with a - Django application for all other HTTP routes: + """HTTP and Websocket GraphQL type router. - ``` + Convenience class to set up GraphQL on both HTTP and Websocket, + optionally with a Django application for all other HTTP routes. + + ```python from strawberry.channels import GraphQLProtocolTypeRouter from django.core.asgi import get_asgi_application @@ -63,3 +64,6 @@ def __init__( ), } ) + + +__all__ = ["GraphQLProtocolTypeRouter"] diff --git a/strawberry/channels/testing.py b/strawberry/channels/testing.py index 496fc32ab5..db3e78e097 100644 --- a/strawberry/channels/testing.py +++ b/strawberry/channels/testing.py @@ -41,8 +41,8 @@ class GraphQLWebsocketCommunicator(WebsocketCommunicator): - """ - Usage: + """A test communicator for GraphQL over Websockets. + ```python import pytest from strawberry.channels.testing import GraphQLWebsocketCommunicator @@ -72,12 +72,16 @@ def __init__( connection_params: dict = {}, **kwargs: Any, ) -> None: - """ + """Create a new communicator. Args: application: Your asgi application that encapsulates the strawberry schema. path: the url endpoint for the schema. protocol: currently this supports `graphql-transport-ws` only. + connection_params: a dictionary of connection parameters to send to the server. + headers: a list of tuples to be sent as headers to the server. + subprotocols: an ordered list of preferred subprotocols to be sent to the server. + **kwargs: additional arguments to be passed to the `WebsocketCommunicator` constructor. """ self.protocol = protocol subprotocols = kwargs.get("subprotocols", []) @@ -155,7 +159,7 @@ async def subscribe( return def process_errors(self, errors: List[GraphQLFormattedError]) -> List[GraphQLError]: - """Reconst a GraphQLError from a FormattedGraphQLError""" + """Reconstructs a GraphQLError from a FormattedGraphQLError.""" result = [] for f_error in errors: error = GraphQLError( @@ -165,3 +169,6 @@ def process_errors(self, errors: List[GraphQLFormattedError]) -> List[GraphQLErr error.path = f_error.get("path", None) result.append(error) return result + + +__all__ = ["GraphQLWebsocketCommunicator"] diff --git a/strawberry/cli/commands/upgrade/__init__.py b/strawberry/cli/commands/upgrade/__init__.py index 5ea4761e23..2b8f387ccb 100644 --- a/strawberry/cli/commands/upgrade/__init__.py +++ b/strawberry/cli/commands/upgrade/__init__.py @@ -11,11 +11,13 @@ from strawberry.cli.app import app from strawberry.codemods.annotated_unions import ConvertUnionToAnnotatedUnion +from strawberry.codemods.update_imports import UpdateImportsCodemod from ._run_codemod import run_codemod codemods = { "annotated-union": ConvertUnionToAnnotatedUnion, + "update-imports": UpdateImportsCodemod, } @@ -46,11 +48,17 @@ def upgrade( python_target_version = tuple(int(x) for x in python_target.split(".")) - transformer = ConvertUnionToAnnotatedUnion( - CodemodContext(), - use_pipe_syntax=python_target_version >= (3, 10), - use_typing_extensions=use_typing_extensions, - ) + transformer: ConvertUnionToAnnotatedUnion | UpdateImportsCodemod + + if codemod == "update-imports": + transformer = UpdateImportsCodemod(context=CodemodContext()) + + else: + transformer = ConvertUnionToAnnotatedUnion( + CodemodContext(), + use_pipe_syntax=python_target_version >= (3, 10), + use_typing_extensions=use_typing_extensions, + ) files: list[str] = [] diff --git a/strawberry/cli/commands/upgrade/_fake_progress.py b/strawberry/cli/commands/upgrade/_fake_progress.py index 6aacc36179..05ba840544 100644 --- a/strawberry/cli/commands/upgrade/_fake_progress.py +++ b/strawberry/cli/commands/upgrade/_fake_progress.py @@ -6,7 +6,8 @@ class FakeProgress: """A fake progress bar that does nothing. - This is used when the user has only one file to process.""" + This is used when the user has only one file to process. + """ def advance(self, task_id: TaskID) -> None: pass diff --git a/strawberry/cli/commands/upgrade/_run_codemod.py b/strawberry/cli/commands/upgrade/_run_codemod.py index d08cbc05e9..04e168e240 100644 --- a/strawberry/cli/commands/upgrade/_run_codemod.py +++ b/strawberry/cli/commands/upgrade/_run_codemod.py @@ -2,6 +2,7 @@ import contextlib import os +from importlib.metadata import version from multiprocessing import Pool, cpu_count from typing import TYPE_CHECKING, Any, Dict, Generator, Sequence, Type, Union @@ -18,13 +19,29 @@ PoolType = Union[Type[Pool], Type[DummyPool]] # type: ignore +def _get_libcst_version() -> tuple[int, int, int]: + package_version_str = version("libcst") + + try: + major, minor, patch = map(int, package_version_str.split(".")) + except ValueError: + major, minor, patch = (0, 0, 0) + + return major, minor, patch + + def _execute_transform_wrap( job: Dict[str, Any], ) -> ExecutionResult: + additional_kwargs: Dict[str, Any] = {} + + if _get_libcst_version() >= (1, 4, 0): + additional_kwargs["scratch"] = {} + # TODO: maybe capture warnings? with open(os.devnull, "w") as null: # noqa: PTH123 with contextlib.redirect_stderr(null): - return _execute_transform(**job) + return _execute_transform(**job, **additional_kwargs) def _get_progress_and_pool( diff --git a/strawberry/codegen/exceptions.py b/strawberry/codegen/exceptions.py index c78454a965..ca7bd6ad10 100644 --- a/strawberry/codegen/exceptions.py +++ b/strawberry/codegen/exceptions.py @@ -12,3 +12,11 @@ class NoOperationNameProvidedError(CodegenError): class MultipleOperationsProvidedError(CodegenError): pass + + +__all__ = [ + "CodegenError", + "NoOperationProvidedError", + "NoOperationNameProvidedError", + "MultipleOperationsProvidedError", +] diff --git a/strawberry/codegen/query_codegen.py b/strawberry/codegen/query_codegen.py index 89449d3c35..92d93d98db 100644 --- a/strawberry/codegen/query_codegen.py +++ b/strawberry/codegen/query_codegen.py @@ -42,19 +42,19 @@ parse, ) -from strawberry.custom_scalar import ScalarDefinition, ScalarWrapper -from strawberry.enum import EnumDefinition -from strawberry.lazy_type import LazyType -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, + StrawberryObjectDefinition, StrawberryOptional, StrawberryType, get_object_definition, has_object_definition, ) -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion -from strawberry.unset import UNSET +from strawberry.types.enum import EnumDefinition +from strawberry.types.lazy_type import LazyType +from strawberry.types.scalar import ScalarDefinition, ScalarWrapper +from strawberry.types.union import StrawberryUnion +from strawberry.types.unset import UNSET from strawberry.utils.str_converters import capitalize_first, to_camel_case from .exceptions import ( @@ -917,3 +917,12 @@ def _collect_enum(self, enum: EnumDefinition) -> GraphQLEnum: ) self._collect_type(graphql_enum) return graphql_enum + + +__all__ = [ + "QueryCodegen", + "QueryCodegenPlugin", + "ConsolePlugin", + "CodegenFile", + "CodegenResult", +] diff --git a/strawberry/codegen/types.py b/strawberry/codegen/types.py index 4d39fc4707..1518cb5f1f 100644 --- a/strawberry/codegen/types.py +++ b/strawberry/codegen/types.py @@ -7,7 +7,7 @@ from enum import EnumMeta from typing_extensions import Literal - from strawberry.unset import UnsetType + from strawberry.types.unset import UnsetType @dataclass @@ -194,3 +194,34 @@ class GraphQLOperation: variables: List[GraphQLVariable] type: GraphQLObjectType variables_type: Optional[GraphQLObjectType] + + +__all__ = [ + "GraphQLOptional", + "GraphQLList", + "GraphQLUnion", + "GraphQLField", + "GraphQLFragmentSpread", + "GraphQLObjectType", + "GraphQLFragmentType", + "GraphQLEnum", + "GraphQLScalar", + "GraphQLType", + "GraphQLFieldSelection", + "GraphQLInlineFragment", + "GraphQLSelection", + "GraphQLStringValue", + "GraphQLIntValue", + "GraphQLFloatValue", + "GraphQLEnumValue", + "GraphQLBoolValue", + "GraphQLNullValue", + "GraphQLListValue", + "GraphQLObjectValue", + "GraphQLVariableReference", + "GraphQLArgumentValue", + "GraphQLArgument", + "GraphQLDirective", + "GraphQLVariable", + "GraphQLOperation", +] diff --git a/strawberry/codemods/update_imports.py b/strawberry/codemods/update_imports.py new file mode 100644 index 0000000000..24e34164f2 --- /dev/null +++ b/strawberry/codemods/update_imports.py @@ -0,0 +1,136 @@ +from __future__ import annotations + +import libcst as cst +import libcst.matchers as m +from libcst.codemod import CodemodContext, VisitorBasedCodemodCommand +from libcst.codemod.visitors import AddImportsVisitor, RemoveImportsVisitor + + +class UpdateImportsCodemod(VisitorBasedCodemodCommand): + def __init__(self, context: CodemodContext) -> None: + super().__init__(context) + self.add_imports_visitor = AddImportsVisitor(context) + self.remove_imports_visitor = RemoveImportsVisitor(context) + + def _update_imports( + self, node: cst.ImportFrom, updated_node: cst.ImportFrom + ) -> cst.ImportFrom: + imports = [ + "field", + "union", + "auto", + "unset", + "arguments", + "lazy_type", + "object_type", + "private", + "enum", + ] + + for import_name in imports: + if m.matches( + node, + m.ImportFrom( + module=m.Attribute( + value=m.Name("strawberry"), attr=m.Name(import_name) + ) + ), + ): + updated_node = updated_node.with_changes( + module=cst.Attribute( + value=cst.Attribute( + value=cst.Name("strawberry"), attr=cst.Name("types") + ), + attr=cst.Name(import_name), + ), + ) + + return updated_node + + def _update_types_types_imports( + self, node: cst.ImportFrom, updated_node: cst.ImportFrom + ) -> cst.ImportFrom: + if m.matches( + node, + m.ImportFrom( + module=m.Attribute( + value=m.Attribute(value=m.Name("strawberry"), attr=m.Name("types")), + attr=m.Name("types"), + ) + ), + ): + updated_node = updated_node.with_changes( + module=cst.Attribute( + value=cst.Attribute( + value=cst.Name("strawberry"), attr=cst.Name("types") + ), + attr=cst.Name("base"), + ), + ) + + return updated_node + + def _update_strawberry_type_imports( + self, node: cst.ImportFrom, updated_node: cst.ImportFrom + ) -> cst.ImportFrom: + if m.matches( + node, + m.ImportFrom( + module=m.Attribute(value=m.Name("strawberry"), attr=m.Name("type")) + ), + ): + has_get_object_definition = ( + any( + m.matches(name, m.ImportAlias(name=m.Name("get_object_definition"))) + for name in node.names + ) + if not isinstance(node.names, cst.ImportStar) + else False + ) + + has_has_object_definition = ( + any( + m.matches(name, m.ImportAlias(name=m.Name("has_object_definition"))) + for name in node.names + ) + if not isinstance(node.names, cst.ImportStar) + else False + ) + + updated_node = updated_node.with_changes( + module=cst.Attribute( + value=cst.Attribute( + value=cst.Name("strawberry"), attr=cst.Name("types") + ), + attr=cst.Name("base"), + ), + ) + + self.remove_imports_visitor.remove_unused_import( + self.context, "strawberry.types.base", "get_object_definition" + ) + + self.remove_imports_visitor.remove_unused_import( + self.context, "strawberry.types.base", "has_object_definition" + ) + + if has_get_object_definition: + self.add_imports_visitor.add_needed_import( + self.context, "strawberry.types", "get_object_definition" + ) + + if has_has_object_definition: + self.add_imports_visitor.add_needed_import( + self.context, "strawberry.types", "has_object_definition" + ) + + return updated_node + + def leave_ImportFrom( + self, node: cst.ImportFrom, updated_node: cst.ImportFrom + ) -> cst.ImportFrom: + updated_node = self._update_imports(updated_node, updated_node) + updated_node = self._update_types_types_imports(updated_node, updated_node) + updated_node = self._update_strawberry_type_imports(updated_node, updated_node) + + return updated_node diff --git a/strawberry/dataloader.py b/strawberry/dataloader.py index a094a892e3..8a04628930 100644 --- a/strawberry/dataloader.py +++ b/strawberry/dataloader.py @@ -267,3 +267,16 @@ async def dispatch_batch(loader: DataLoader, batch: Batch) -> None: except Exception as e: for task in batch.tasks: task.future.set_exception(e) + + +__all__ = [ + "DataLoader", + "Batch", + "LoaderTask", + "AbstractCache", + "DefaultCache", + "should_create_new_batch", + "get_current_batch", + "dispatch", + "dispatch_batch", +] diff --git a/strawberry/directive.py b/strawberry/directive.py index 8fe9e7ed84..17eaafd0c8 100644 --- a/strawberry/directive.py +++ b/strawberry/directive.py @@ -7,21 +7,45 @@ from graphql import DirectiveLocation -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField from strawberry.types.fields.resolver import ( INFO_PARAMSPEC, ReservedType, StrawberryResolver, ) -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET if TYPE_CHECKING: import inspect - from strawberry.arguments import StrawberryArgument + from strawberry.types.arguments import StrawberryArgument -def directive_field(name: str, default: object = UNSET) -> Any: +# TODO: should this be directive argument? +def directive_field( + name: str, + default: object = UNSET, +) -> Any: + """Function to add metadata to a directive argument, like the GraphQL name. + + Args: + name: The GraphQL name of the directive argument + default: The default value of the argument + + Returns: + A StrawberryField object that can be used to customise a directive argument + + Example: + ```python + import strawberry + from strawberry.schema_directive import Location + + + @strawberry.schema_directive(locations=[Location.FIELD_DEFINITION]) + class Sensitive: + reason: str = strawberry.directive_field(name="as") + ``` + """ return StrawberryField( python_name=None, graphql_name=name, @@ -74,6 +98,30 @@ def directive( description: Optional[str] = None, name: Optional[str] = None, ) -> Callable[[Callable[..., T]], StrawberryDirective[T]]: + """Decorator to create a GraphQL operation directive. + + Args: + locations: The locations where the directive can be used + description: The GraphQL description of the directive + name: The GraphQL name of the directive + + Returns: + A StrawberryDirective object that can be used to customise a directive + + Example: + ```python + import strawberry + from strawberry.directive import DirectiveLocation + + + @strawberry.directive( + locations=[DirectiveLocation.FIELD], description="Make string uppercase" + ) + def turn_uppercase(value: str): + return value.upper() + ``` + """ + def _wrap(f: Callable[..., T]) -> StrawberryDirective[T]: return StrawberryDirective( python_name=f.__name__, diff --git a/strawberry/django/context.py b/strawberry/django/context.py index 43746f9056..b1705cdae1 100644 --- a/strawberry/django/context.py +++ b/strawberry/django/context.py @@ -18,5 +18,8 @@ def __getitem__(self, key: str) -> Any: return super().__getattribute__(key) def get(self, key: str) -> Any: - """Enable .get notation for accessing the request""" + """Enable .get notation for accessing the request.""" return super().__getattribute__(key) + + +__all__ = ["StrawberryDjangoContext"] diff --git a/strawberry/django/test/client.py b/strawberry/django/test/client.py index c3d15c9de4..1ce5ab4df4 100644 --- a/strawberry/django/test/client.py +++ b/strawberry/django/test/client.py @@ -18,3 +18,6 @@ def request( return self._client.post( self.url, data=body, content_type="application/json", headers=headers ) + + +__all__ = ["GraphQLTestClient"] diff --git a/strawberry/django/views.py b/strawberry/django/views.py index 88fb55c267..54a16d8fa1 100644 --- a/strawberry/django/views.py +++ b/strawberry/django/views.py @@ -287,3 +287,6 @@ async def render_graphql_ide(self, request: HttpRequest) -> HttpResponse: response.content = template.render(RequestContext(request, context)) return response + + +__all__ = ["GraphQLView", "AsyncGraphQLView"] diff --git a/strawberry/exceptions/__init__.py b/strawberry/exceptions/__init__.py index fa996a5886..7d3b3ccb1b 100644 --- a/strawberry/exceptions/__init__.py +++ b/strawberry/exceptions/__init__.py @@ -25,7 +25,7 @@ if TYPE_CHECKING: from graphql import GraphQLInputObjectType, GraphQLObjectType - from strawberry.type import StrawberryType + from strawberry.types.base import StrawberryType from .exception_source import ExceptionSource @@ -34,7 +34,7 @@ # TODO: this doesn't seem to be tested class WrongReturnTypeForUnion(Exception): - """The Union type cannot be resolved because it's not a field""" + """The Union type cannot be resolved because it's not a field.""" def __init__(self, field_name: str, result_type: str) -> None: message = ( @@ -46,7 +46,7 @@ def __init__(self, field_name: str, result_type: str) -> None: class UnallowedReturnTypeForUnion(Exception): - """The return type is not in the list of Union types""" + """The return type is not in the list of Union types.""" def __init__( self, field_name: str, result_type: str, allowed_types: Set[GraphQLObjectType] @@ -144,7 +144,7 @@ def __init__(self) -> None: class InvalidCustomContext(Exception): - """Raised when a custom context object is of the wrong python type""" + """Raised when a custom context object is of the wrong python type.""" def __init__(self) -> None: message = ( @@ -155,7 +155,7 @@ def __init__(self) -> None: class StrawberryGraphQLError(GraphQLError): - """Use it when you want to override the graphql.GraphQLError in custom extensions""" + """Use it when you want to override the graphql.GraphQLError in custom extensions.""" __all__ = [ diff --git a/strawberry/exceptions/duplicated_type_name.py b/strawberry/exceptions/duplicated_type_name.py index 7e640fc50e..9f3eb691f3 100644 --- a/strawberry/exceptions/duplicated_type_name.py +++ b/strawberry/exceptions/duplicated_type_name.py @@ -13,7 +13,7 @@ class DuplicatedTypeName(StrawberryException): - """Raised when the same type with different definition is reused inside a schema""" + """Raised when the same type with different definition is reused inside a schema.""" def __init__( self, diff --git a/strawberry/exceptions/invalid_argument_type.py b/strawberry/exceptions/invalid_argument_type.py index 1b03ebf7d1..092b8ad6d0 100644 --- a/strawberry/exceptions/invalid_argument_type.py +++ b/strawberry/exceptions/invalid_argument_type.py @@ -3,13 +3,13 @@ from functools import cached_property from typing import TYPE_CHECKING, Optional -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition from .exception import StrawberryException from .utils.source_finder import SourceFinder if TYPE_CHECKING: - from strawberry.arguments import StrawberryArgument + from strawberry.types.arguments import StrawberryArgument from strawberry.types.fields.resolver import StrawberryResolver from .exception_source import ExceptionSource @@ -21,7 +21,7 @@ def __init__( resolver: StrawberryResolver, argument: StrawberryArgument, ) -> None: - from strawberry.union import StrawberryUnion + from strawberry.types.union import StrawberryUnion self.function = resolver.wrapped_func self.argument_name = argument.python_name diff --git a/strawberry/exceptions/invalid_union_type.py b/strawberry/exceptions/invalid_union_type.py index cd54b8dfae..28e65de6c5 100644 --- a/strawberry/exceptions/invalid_union_type.py +++ b/strawberry/exceptions/invalid_union_type.py @@ -10,13 +10,13 @@ from .exception import StrawberryException if TYPE_CHECKING: - from strawberry.union import StrawberryUnion + from strawberry.types.union import StrawberryUnion from .exception_source import ExceptionSource class InvalidUnionTypeError(StrawberryException): - """The union is constructed with an invalid type""" + """The union is constructed with an invalid type.""" invalid_type: object @@ -26,8 +26,8 @@ def __init__( invalid_type: object, union_definition: Optional[StrawberryUnion] = None, ) -> None: - from strawberry.custom_scalar import ScalarWrapper - from strawberry.type import StrawberryList + from strawberry.types.base import StrawberryList + from strawberry.types.scalar import ScalarWrapper self.union_name = union_name self.invalid_type = invalid_type @@ -78,8 +78,7 @@ def exception_source(self) -> Optional[ExceptionSource]: class InvalidTypeForUnionMergeError(StrawberryException): - """A specialized version of InvalidUnionTypeError for when trying - to merge unions using the pipe operator.""" + """A specialized version of InvalidUnionTypeError for when trying to merge unions using the pipe operator.""" invalid_type: Type diff --git a/strawberry/exceptions/missing_arguments_annotations.py b/strawberry/exceptions/missing_arguments_annotations.py index 825019339d..97610584fa 100644 --- a/strawberry/exceptions/missing_arguments_annotations.py +++ b/strawberry/exceptions/missing_arguments_annotations.py @@ -13,7 +13,7 @@ class MissingArgumentsAnnotationsError(StrawberryException): - """The field is missing the annotation for one or more arguments""" + """The field is missing the annotation for one or more arguments.""" def __init__( self, diff --git a/strawberry/exceptions/missing_dependencies.py b/strawberry/exceptions/missing_dependencies.py index 1f0746a713..fa72f17ea3 100644 --- a/strawberry/exceptions/missing_dependencies.py +++ b/strawberry/exceptions/missing_dependencies.py @@ -4,8 +4,7 @@ class MissingOptionalDependenciesError(Exception): - """Some optional dependencies that are required for a particular - task are missing.""" + """Some optional dependencies that are required for a particular task are missing.""" def __init__( self, @@ -13,8 +12,17 @@ def __init__( packages: Optional[list[str]] = None, extras: Optional[list[str]] = None, ) -> None: + """Initialize the error. + + Args: + packages: List of packages that are required but missing. + extras: List of extras that are required but missing. + """ packages = packages or [] + if extras: packages.append(f"'strawberry-graphql[{','.join(extras)}]'") + hint = f" (hint: pip install {' '.join(packages)})" if packages else "" + self.message = f"Some optional dependencies are missing{hint}" diff --git a/strawberry/exceptions/missing_return_annotation.py b/strawberry/exceptions/missing_return_annotation.py index 4fad8db98c..60d64bffa0 100644 --- a/strawberry/exceptions/missing_return_annotation.py +++ b/strawberry/exceptions/missing_return_annotation.py @@ -13,7 +13,7 @@ class MissingReturnAnnotationError(StrawberryException): - """The field is missing the return annotation""" + """The field is missing the return annotation.""" def __init__( self, diff --git a/strawberry/exceptions/permission_fail_silently_requires_optional.py b/strawberry/exceptions/permission_fail_silently_requires_optional.py index 4b8de1a046..9a922e2f8e 100644 --- a/strawberry/exceptions/permission_fail_silently_requires_optional.py +++ b/strawberry/exceptions/permission_fail_silently_requires_optional.py @@ -20,7 +20,7 @@ def __init__(self, field: StrawberryField) -> None: self.rich_message = ( "fail_silently permissions can only be used with fields of type " f"optional or list. Provided field `[underline]{field.name}[/]` " - f"is of type `[underline]{field.type.__name__}[/]`" # type: ignore + f"is of type `[underline]{field.type.__name__}[/]`" ) self.annotation_message = "field defined here" self.suggestion = ( @@ -38,14 +38,14 @@ def exception_source(self) -> Optional[ExceptionSource]: source = None if origin is not None: source = source_finder.find_class_attribute_from_object( - origin, # type: ignore + origin, self.field.python_name, ) # in case it is a function if source is None and self.field.base_resolver is not None: source = source_finder.find_function_from_object( - self.field.base_resolver.wrapped_func # type: ignore + self.field.base_resolver.wrapped_func ) return source diff --git a/strawberry/exceptions/scalar_already_registered.py b/strawberry/exceptions/scalar_already_registered.py index d20a2bf0a2..c950b5d369 100644 --- a/strawberry/exceptions/scalar_already_registered.py +++ b/strawberry/exceptions/scalar_already_registered.py @@ -9,7 +9,7 @@ from .exception import StrawberryException if TYPE_CHECKING: - from strawberry.custom_scalar import ScalarDefinition + from strawberry.types.scalar import ScalarDefinition from .exception_source import ExceptionSource diff --git a/strawberry/exceptions/unresolved_field_type.py b/strawberry/exceptions/unresolved_field_type.py index 6f0e5f4a65..70eff59ed4 100644 --- a/strawberry/exceptions/unresolved_field_type.py +++ b/strawberry/exceptions/unresolved_field_type.py @@ -8,8 +8,8 @@ from .exception import StrawberryException if TYPE_CHECKING: - from strawberry.field import StrawberryField - from strawberry.object_type import StrawberryObjectDefinition + from strawberry.types.field import StrawberryField + from strawberry.types.object_type import StrawberryObjectDefinition from .exception_source import ExceptionSource diff --git a/strawberry/exceptions/utils/source_finder.py b/strawberry/exceptions/utils/source_finder.py index 2aec969cf8..9b2c8010d0 100644 --- a/strawberry/exceptions/utils/source_finder.py +++ b/strawberry/exceptions/utils/source_finder.py @@ -15,8 +15,8 @@ from libcst import BinaryOperation, Call, CSTNode, FunctionDef - from strawberry.custom_scalar import ScalarDefinition - from strawberry.union import StrawberryUnion + from strawberry.types.scalar import ScalarDefinition + from strawberry.types.union import StrawberryUnion @dataclass @@ -605,3 +605,6 @@ def find_annotated_union( if self.cst else None ) + + +__all__ = ["SourceFinder"] diff --git a/strawberry/experimental/pydantic/conversion.py b/strawberry/experimental/pydantic/conversion.py index 601ea7e90d..ae3d2aaddb 100644 --- a/strawberry/experimental/pydantic/conversion.py +++ b/strawberry/experimental/pydantic/conversion.py @@ -4,17 +4,17 @@ import dataclasses from typing import TYPE_CHECKING, Any, Type, Union, cast -from strawberry.enum import EnumDefinition -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, StrawberryOptional, has_object_definition, ) -from strawberry.union import StrawberryUnion +from strawberry.types.enum import EnumDefinition +from strawberry.types.union import StrawberryUnion if TYPE_CHECKING: - from strawberry.field import StrawberryField - from strawberry.type import StrawberryType + from strawberry.types.base import StrawberryType + from strawberry.types.field import StrawberryField def _convert_from_pydantic_to_strawberry_type( diff --git a/strawberry/experimental/pydantic/conversion_types.py b/strawberry/experimental/pydantic/conversion_types.py index 07af215811..0e24ba2f00 100644 --- a/strawberry/experimental/pydantic/conversion_types.py +++ b/strawberry/experimental/pydantic/conversion_types.py @@ -6,7 +6,7 @@ from pydantic import BaseModel if TYPE_CHECKING: - from strawberry.types.types import StrawberryObjectDefinition + from strawberry.types.base import StrawberryObjectDefinition PydanticModel = TypeVar("PydanticModel", bound=BaseModel) @@ -14,7 +14,9 @@ class StrawberryTypeFromPydantic(Protocol[PydanticModel]): """This class does not exist in runtime. - It only makes the methods below visible for IDEs""" + + It only makes the methods below visible for IDEs. + """ def __init__(self, **kwargs: Any) -> None: ... diff --git a/strawberry/experimental/pydantic/error_type.py b/strawberry/experimental/pydantic/error_type.py index 6ef78dbb6b..bbedfe610b 100644 --- a/strawberry/experimental/pydantic/error_type.py +++ b/strawberry/experimental/pydantic/error_type.py @@ -16,7 +16,6 @@ from pydantic import BaseModel -from strawberry.auto import StrawberryAuto from strawberry.experimental.pydantic._compat import ( CompatModelField, PydanticCompat, @@ -27,7 +26,8 @@ get_strawberry_type_from_model, normalize_type, ) -from strawberry.object_type import _process_type, _wrap_dataclass +from strawberry.types.auto import StrawberryAuto +from strawberry.types.object_type import _process_type, _wrap_dataclass from strawberry.types.type_resolver import _get_fields from strawberry.utils.typing import get_list_annotation, is_list diff --git a/strawberry/experimental/pydantic/fields.py b/strawberry/experimental/pydantic/fields.py index 0d4183f59e..9cac486290 100644 --- a/strawberry/experimental/pydantic/fields.py +++ b/strawberry/experimental/pydantic/fields.py @@ -13,7 +13,7 @@ from strawberry.experimental.pydantic.exceptions import ( UnregisteredTypeException, ) -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import StrawberryObjectDefinition try: from types import UnionType as TypingUnionType @@ -51,7 +51,7 @@ def replace_pydantic_types(type_: Any, is_input: bool) -> Any: def replace_types_recursively( type_: Any, is_input: bool, compat: PydanticCompat ) -> Any: - """Runs the conversions recursively into the arguments of generic types if any""" + """Runs the conversions recursively into the arguments of generic types if any.""" basic_type = compat.get_basic_type(type_) replaced_type = replace_pydantic_types(basic_type, is_input) diff --git a/strawberry/experimental/pydantic/object_type.py b/strawberry/experimental/pydantic/object_type.py index 005b89a2b0..caed153c9b 100644 --- a/strawberry/experimental/pydantic/object_type.py +++ b/strawberry/experimental/pydantic/object_type.py @@ -17,7 +17,6 @@ ) from strawberry.annotation import StrawberryAnnotation -from strawberry.auto import StrawberryAuto from strawberry.experimental.pydantic._compat import ( CompatModelField, PydanticCompat, @@ -34,8 +33,9 @@ get_default_factory_for_field, get_private_fields, ) -from strawberry.field import StrawberryField -from strawberry.object_type import _process_type, _wrap_dataclass +from strawberry.types.auto import StrawberryAuto +from strawberry.types.field import StrawberryField +from strawberry.types.object_type import _process_type, _wrap_dataclass from strawberry.types.type_resolver import _get_fields from strawberry.utils.dataclasses import add_custom_init_fn @@ -312,8 +312,10 @@ def input( use_pydantic_alias: bool = True, ) -> Callable[..., Type[StrawberryTypeFromPydantic[PydanticModel]]]: """Convenience decorator for creating an input type from a Pydantic model. - Equal to partial(type, is_input=True) - See https://github.com/strawberry-graphql/strawberry/issues/1830 + + Equal to `partial(type, is_input=True)` + + See https://github.com/strawberry-graphql/strawberry/issues/1830. """ return type( model=model, @@ -340,8 +342,10 @@ def interface( use_pydantic_alias: bool = True, ) -> Callable[..., Type[StrawberryTypeFromPydantic[PydanticModel]]]: """Convenience decorator for creating an interface type from a Pydantic model. - Equal to partial(type, is_interface=True) - See https://github.com/strawberry-graphql/strawberry/issues/1830 + + Equal to `partial(type, is_interface=True)` + + See https://github.com/strawberry-graphql/strawberry/issues/1830. """ return type( model=model, diff --git a/strawberry/experimental/pydantic/utils.py b/strawberry/experimental/pydantic/utils.py index ec253a2120..912553fb98 100644 --- a/strawberry/experimental/pydantic/utils.py +++ b/strawberry/experimental/pydantic/utils.py @@ -25,8 +25,8 @@ BothDefaultAndDefaultFactoryDefinedError, UnregisteredTypeException, ) -from strawberry.private import is_private -from strawberry.unset import UNSET +from strawberry.types.private import is_private +from strawberry.types.unset import UNSET from strawberry.utils.typing import ( get_list_annotation, get_optional_annotation, @@ -60,7 +60,7 @@ def get_private_fields(cls: Type) -> List[dataclasses.Field]: class DataclassCreationFields(NamedTuple): - """Fields required for the fields parameter of make_dataclass""" + """Fields required for the fields parameter of make_dataclass.""" name: str field_type: Type @@ -75,8 +75,7 @@ def get_default_factory_for_field( field: CompatModelField, compat: PydanticCompat, ) -> Union[NoArgAnyCallable, dataclasses._MISSING_TYPE]: - """ - Gets the default factory for a pydantic field. + """Gets the default factory for a pydantic field. Handles mutable defaults when making the dataclass by using pydantic's smart_deepcopy diff --git a/strawberry/ext/dataclasses/dataclasses.py b/strawberry/ext/dataclasses/dataclasses.py index 5667c5c4c3..820649c18d 100644 --- a/strawberry/ext/dataclasses/dataclasses.py +++ b/strawberry/ext/dataclasses/dataclasses.py @@ -21,7 +21,8 @@ def dataclass_init_fn( self_name: str, globals_: Dict[str, Any], ) -> Any: - """ + """Create an __init__ function for a dataclass. + We create a custom __init__ function for the dataclasses that back Strawberry object types to only accept keyword arguments. This allows us to avoid the problem where a type cannot define a field with a default value diff --git a/strawberry/ext/mypy_plugin.py b/strawberry/ext/mypy_plugin.py index 849732e3da..3530931933 100644 --- a/strawberry/ext/mypy_plugin.py +++ b/strawberry/ext/mypy_plugin.py @@ -92,7 +92,7 @@ class MypyVersion: - """Stores the mypy version to be used by the plugin""" + """Stores the mypy version to be used by the plugin.""" VERSION: Decimal @@ -330,9 +330,11 @@ def add_static_method_to_class( return_type: Type, tvar_def: Optional[TypeVarType] = None, ) -> None: - """Adds a static method - Edited add_method_to_class to incorporate static method logic - https://github.com/python/mypy/blob/9c05d3d19/mypy/plugins/common.py + """Adds a static method. + + Edited `add_method_to_class` to incorporate static method logic + + https://github.com/python/mypy/blob/9c05d3d19/mypy/plugins/common.py. """ info = cls.info @@ -555,22 +557,22 @@ def get_class_decorator_hook( return None def _is_strawberry_union(self, fullname: str) -> bool: - return fullname == "strawberry.union.union" or fullname.endswith( + return fullname == "strawberry.types.union.union" or fullname.endswith( "strawberry.union" ) def _is_strawberry_enum(self, fullname: str) -> bool: - return fullname == "strawberry.enum.enum" or fullname.endswith( + return fullname == "strawberry.types.enum.enum" or fullname.endswith( "strawberry.enum" ) def _is_strawberry_scalar(self, fullname: str) -> bool: - return fullname == "strawberry.custom_scalar.scalar" or fullname.endswith( + return fullname == "strawberry.types.scalar.scalar" or fullname.endswith( "strawberry.scalar" ) def _is_strawberry_lazy_type(self, fullname: str) -> bool: - return fullname == "strawberry.lazy_type.LazyType" + return fullname == "strawberry.types.lazy_type.LazyType" def _is_strawberry_create_type(self, fullname: str) -> bool: # using endswith(.create_type) is not ideal as there might be diff --git a/strawberry/extensions/add_validation_rules.py b/strawberry/extensions/add_validation_rules.py index a4ac666546..763ef70b05 100644 --- a/strawberry/extensions/add_validation_rules.py +++ b/strawberry/extensions/add_validation_rules.py @@ -9,31 +9,32 @@ class AddValidationRules(SchemaExtension): - """ - Add graphql-core validation rules + """Add graphql-core validation rules. Example: - - >>> import strawberry - >>> from strawberry.extensions import AddValidationRules - >>> from graphql import ValidationRule, GraphQLError - >>> - >>> class MyCustomRule(ValidationRule): - ... def enter_field(self, node, *args) -> None: - ... if node.name.value == "secret_field": - ... self.report_error( - ... GraphQLError("Can't query field 'secret_field'") - ... ) - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... AddValidationRules([ - ... MyCustomRule, - ... ]), - ... ] - ... ) - + ```python + import strawberry + from strawberry.extensions import AddValidationRules + from graphql import ValidationRule, GraphQLError + + + class MyCustomRule(ValidationRule): + def enter_field(self, node, *args) -> None: + if node.name.value == "secret_field": + self.report_error(GraphQLError("Can't query field 'secret_field'")) + + + schema = strawberry.Schema( + Query, + extensions=[ + AddValidationRules( + [ + MyCustomRule, + ] + ), + ], + ) + ``` """ validation_rules: List[Type[ASTValidationRule]] @@ -46,3 +47,6 @@ def on_operation(self) -> Iterator[None]: self.execution_context.validation_rules + tuple(self.validation_rules) ) yield + + +__all__ = ["AddValidationRules"] diff --git a/strawberry/extensions/base_extension.py b/strawberry/extensions/base_extension.py index 60ff64dfcd..92160315f0 100644 --- a/strawberry/extensions/base_extension.py +++ b/strawberry/extensions/base_extension.py @@ -27,25 +27,25 @@ def __init__(self, *, execution_context: ExecutionContext) -> None: def on_operation( # type: ignore self, ) -> AsyncIteratorOrIterator[None]: # pragma: no cover - """Called before and after a GraphQL operation (query / mutation) starts""" + """Called before and after a GraphQL operation (query / mutation) starts.""" yield None def on_validate( # type: ignore self, ) -> AsyncIteratorOrIterator[None]: # pragma: no cover - """Called before and after the validation step""" + """Called before and after the validation step.""" yield None def on_parse( # type: ignore self, ) -> AsyncIteratorOrIterator[None]: # pragma: no cover - """Called before and after the parsing step""" + """Called before and after the parsing step.""" yield None def on_execute( # type: ignore self, ) -> AsyncIteratorOrIterator[None]: # pragma: no cover - """Called before and after the execution step""" + """Called before and after the execution step.""" yield None def resolve( @@ -70,3 +70,5 @@ def get_results(self) -> AwaitableOrValue[Dict[str, Any]]: SchemaExtension.on_parse.__name__, SchemaExtension.on_execute.__name__, } + +__all__ = ["SchemaExtension", "Hook", "HOOK_METHODS", "LifecycleStep"] diff --git a/strawberry/extensions/directives.py b/strawberry/extensions/directives.py index 87a4ce5d5a..b72923adda 100644 --- a/strawberry/extensions/directives.py +++ b/strawberry/extensions/directives.py @@ -11,8 +11,8 @@ from graphql import DirectiveNode, GraphQLResolveInfo from strawberry.directive import StrawberryDirective - from strawberry.field import StrawberryField from strawberry.schema.schema import Schema + from strawberry.types.field import StrawberryField from strawberry.utils.await_maybe import AwaitableOrValue @@ -85,3 +85,6 @@ def process_directive( if value_parameter: arguments[value_parameter.name] = value return strawberry_directive, arguments + + +__all__ = ["DirectivesExtension", "DirectivesExtensionSync"] diff --git a/strawberry/extensions/disable_validation.py b/strawberry/extensions/disable_validation.py index db0fff3ee8..cd9aeafaed 100644 --- a/strawberry/extensions/disable_validation.py +++ b/strawberry/extensions/disable_validation.py @@ -4,21 +4,21 @@ class DisableValidation(SchemaExtension): - """ - Disable query validation + """Disable query validation. Example: - >>> import strawberry - >>> from strawberry.extensions import DisableValidation - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... DisableValidation, - ... ] - ... ) - + ```python + import strawberry + from strawberry.extensions import DisableValidation + + schema = strawberry.Schema( + Query, + extensions=[ + DisableValidation, + ], + ) + ``` """ def __init__(self) -> None: @@ -29,3 +29,6 @@ def __init__(self) -> None: def on_operation(self) -> Iterator[None]: self.execution_context.validation_rules = () # remove all validation_rules yield + + +__all__ = ["DisableValidation"] diff --git a/strawberry/extensions/field_extension.py b/strawberry/extensions/field_extension.py index 15786f4e8d..afb70e53ab 100644 --- a/strawberry/extensions/field_extension.py +++ b/strawberry/extensions/field_extension.py @@ -7,8 +7,8 @@ if TYPE_CHECKING: from typing_extensions import TypeAlias - from strawberry.field import StrawberryField from strawberry.types import Info + from strawberry.types.field import StrawberryField SyncExtensionResolver: TypeAlias = Callable[..., Any] @@ -44,7 +44,9 @@ def supports_async(self) -> bool: class SyncToAsyncExtension(FieldExtension): """Helper class for mixing async extensions with sync resolvers. - Applied automatically""" + + Applied automatically. + """ async def resolve_async( self, next_: AsyncExtensionResolver, source: Any, info: Info, **kwargs: Any @@ -67,11 +69,12 @@ def _get_async_resolvers( def build_field_extension_resolvers( field: StrawberryField, ) -> list[Union[SyncExtensionResolver, AsyncExtensionResolver]]: - """ + """Builds a list of resolvers for a field with extensions. + Verifies that all of the field extensions for a given field support sync or async depending on the field resolver. - Inserts a SyncToAsyncExtension to be able to - use Async extensions on sync resolvers + + Inserts a SyncToAsyncExtension to be able to use Async extensions on sync resolvers Throws a TypeError otherwise. Returns True if resolving should be async, False on sync resolving @@ -151,3 +154,6 @@ def build_field_extension_resolvers( f"If possible try to change the execution order so that all sync-only " f"extensions are executed first." ) + + +__all__ = ["FieldExtension"] diff --git a/strawberry/extensions/mask_errors.py b/strawberry/extensions/mask_errors.py index 450b9900b9..5cb0ffbaa7 100644 --- a/strawberry/extensions/mask_errors.py +++ b/strawberry/extensions/mask_errors.py @@ -44,3 +44,6 @@ def on_operation(self) -> Iterator[None]: processed_errors.append(error) result.errors = processed_errors + + +__all__ = ["MaskErrors"] diff --git a/strawberry/extensions/max_aliases.py b/strawberry/extensions/max_aliases.py index 0d1358e44a..b1d0aba268 100644 --- a/strawberry/extensions/max_aliases.py +++ b/strawberry/extensions/max_aliases.py @@ -13,36 +13,35 @@ class MaxAliasesLimiter(AddValidationRules): - """ - Add a validator to limit the number of aliases used. + """Add a validator to limit the number of aliases used. Example: - >>> import strawberry - >>> from strawberry.extensions import MaxAliasesLimiter - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... MaxAliasesLimiter(max_alias_count=15) - ... ] - ... ) - - Arguments: + ```python + import strawberry + from strawberry.extensions import MaxAliasesLimiter - `max_alias_count: int` - The maximum number of aliases allowed in a GraphQL document. + schema = strawberry.Schema(Query, extensions=[MaxAliasesLimiter(max_alias_count=15)]) + ``` """ - def __init__( - self, - max_alias_count: int, - ) -> None: + def __init__(self, max_alias_count: int) -> None: + """Initialize the MaxAliasesLimiter. + + Args: + max_alias_count: The maximum number of aliases allowed in a GraphQL document. + """ validator = create_validator(max_alias_count) super().__init__([validator]) def create_validator(max_alias_count: int) -> Type[ValidationRule]: + """Create a validator that checks the number of aliases in a document. + + Args: + max_alias_count: The maximum number of aliases allowed in a GraphQL document. + """ + class MaxAliasesValidator(ValidationRule): def __init__(self, validation_context: ValidationContext) -> None: document = validation_context.document @@ -82,3 +81,6 @@ def count_fields_with_alias( result += count_fields_with_alias(selection) return result + + +__all__ = ["MaxAliasesLimiter"] diff --git a/strawberry/extensions/max_tokens.py b/strawberry/extensions/max_tokens.py index 1338cdb19a..60accd8a8a 100644 --- a/strawberry/extensions/max_tokens.py +++ b/strawberry/extensions/max_tokens.py @@ -4,25 +4,15 @@ class MaxTokensLimiter(SchemaExtension): - """ - Add a validator to limit the number of tokens in a GraphQL document. + """Add a validator to limit the number of tokens in a GraphQL document. Example: + ```python + import strawberry + from strawberry.extensions import MaxTokensLimiter - >>> import strawberry - >>> from strawberry.extensions import MaxTokensLimiter - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... MaxTokensLimiter(max_token_count=1000) - ... ] - ... ) - - Arguments: - - `max_token_count: int` - The maximum number of tokens allowed in a GraphQL document. + schema = strawberry.Schema(Query, extensions=[MaxTokensLimiter(max_token_count=1000)]) + ``` The following things are counted as tokens: * various brackets: "{", "}", "(", ")" @@ -37,8 +27,16 @@ def __init__( self, max_token_count: int, ) -> None: + """Initialize the MaxTokensLimiter. + + Args: + max_token_count: The maximum number of tokens allowed in a GraphQL document. + """ self.max_token_count = max_token_count def on_operation(self) -> Iterator[None]: self.execution_context.parse_options["max_tokens"] = self.max_token_count yield + + +__all__ = ["MaxTokensLimiter"] diff --git a/strawberry/extensions/parser_cache.py b/strawberry/extensions/parser_cache.py index 223621e63c..39b28c039b 100644 --- a/strawberry/extensions/parser_cache.py +++ b/strawberry/extensions/parser_cache.py @@ -6,31 +6,31 @@ class ParserCache(SchemaExtension): - """ - Add LRU caching the parsing step during execution to improve performance. + """Add LRU caching the parsing step during execution to improve performance. Example: - >>> import strawberry - >>> from strawberry.extensions import ParserCache - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... ParserCache(maxsize=100), - ... ] - ... ) - - Arguments: - - `maxsize: Optional[int]` - Set the maxsize of the cache. If `maxsize` is set to `None` then the - cache will grow without bound. - More info: https://docs.python.org/3/library/functools.html#functools.lru_cache - + ```python + import strawberry + from strawberry.extensions import ParserCache + + schema = strawberry.Schema( + Query, + extensions=[ + ParserCache(maxsize=100), + ], + ) + ``` """ def __init__(self, maxsize: Optional[int] = None) -> None: + """Initialize the ParserCache. + + Args: + maxsize: Set the maxsize of the cache. If `maxsize` is set to `None` then the + cache will grow without bound. + More info: https://docs.python.org/3/library/functools.html#functools.lru_cache + """ self.cached_parse_document = lru_cache(maxsize=maxsize)(parse_document) def on_parse(self) -> Iterator[None]: @@ -40,3 +40,6 @@ def on_parse(self) -> Iterator[None]: execution_context.query, **execution_context.parse_options ) yield + + +__all__ = ["ParserCache"] diff --git a/strawberry/extensions/pyinstrument.py b/strawberry/extensions/pyinstrument.py index 44735c91ce..53dd9fe66a 100644 --- a/strawberry/extensions/pyinstrument.py +++ b/strawberry/extensions/pyinstrument.py @@ -9,9 +9,7 @@ class PyInstrument(SchemaExtension): - """ - Extension to profile the execution time of resolvers using PyInstrument. - """ + """Extension to profile the execution time of resolvers using PyInstrument.""" def __init__( self, @@ -20,11 +18,6 @@ def __init__( self._report_path = report_path def on_operation(self) -> Iterator[None]: - """ - Called when an operation is started, - in this case we start the profiler and yield - then we stop the profiler when the operation is done - """ profiler = Profiler() profiler.start() @@ -33,3 +26,6 @@ def on_operation(self) -> Iterator[None]: profiler.stop() Path(self._report_path, encoding="utf-8").write_text(profiler.output_html()) + + +__all__ = ["PyInstrument"] diff --git a/strawberry/extensions/query_depth_limiter.py b/strawberry/extensions/query_depth_limiter.py index f5ebe24d4f..f23831a00b 100644 --- a/strawberry/extensions/query_depth_limiter.py +++ b/strawberry/extensions/query_depth_limiter.py @@ -81,32 +81,19 @@ class IgnoreContext: class QueryDepthLimiter(AddValidationRules): - """ - Add a validator to limit the query depth of GraphQL operations + """Add a validator to limit the query depth of GraphQL operations. Example: - >>> import strawberry - >>> from strawberry.extensions import QueryDepthLimiter - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... QueryDepthLimiter(max_depth=4) - ... ] - ... ) - - Arguments: - - `max_depth: int` - The maximum allowed depth for any operation in a GraphQL document. - `callback: Optional[Callable[[Dict[str, int]], None]` - Called each time validation runs. Receives an Object which is a - map of the depths for each operation. - `should_ignore: Optional[ShouldIgnoreType]` - Stops recursive depth checking based on a field name and arguments. - A function that returns a boolean and conforms to the ShouldIgnoreType - function signature. + ```python + import strawberry + from strawberry.extensions import QueryDepthLimiter + + schema = strawberry.Schema( + Query, + extensions=[QueryDepthLimiter(max_depth=4)], + ) + ``` """ def __init__( @@ -115,6 +102,15 @@ def __init__( callback: Optional[Callable[[Dict[str, int]], None]] = None, should_ignore: Optional[ShouldIgnoreType] = None, ) -> None: + """Initialize the QueryDepthLimiter. + + Args: + max_depth: The maximum allowed depth for any operation in a GraphQL document. + callback: Called each time validation runs. + Receives an Object which is a map of the depths for each operation. + should_ignore: Stops recursive depth checking based on a field name and arguments. + A function that returns a boolean and conforms to the ShouldIgnoreType function signature. + """ if should_ignore is not None and not callable(should_ignore): raise TypeError( "The `should_ignore` argument to " @@ -317,3 +313,6 @@ def is_ignored(node: FieldNode, ignore: Optional[List[IgnoreType]] = None) -> bo raise TypeError(f"Invalid ignore option: {rule}") return False + + +__all__ = ["QueryDepthLimiter"] diff --git a/strawberry/extensions/runner.py b/strawberry/extensions/runner.py index 4487dff1f8..44d12ac009 100644 --- a/strawberry/extensions/runner.py +++ b/strawberry/extensions/runner.py @@ -84,3 +84,6 @@ def as_middleware_manager(self, *additional_middlewares: Any) -> MiddlewareManag middlewares = tuple(self.extensions) + additional_middlewares return MiddlewareManager(*middlewares) + + +__all__ = ["SchemaExtensionsRunner"] diff --git a/strawberry/extensions/tracing/apollo.py b/strawberry/extensions/tracing/apollo.py index 043c441fcc..2245f54643 100644 --- a/strawberry/extensions/tracing/apollo.py +++ b/strawberry/extensions/tracing/apollo.py @@ -191,3 +191,6 @@ def resolve( end_timestamp = self.now() resolver_stats.duration = end_timestamp - start_timestamp self._resolver_stats.append(resolver_stats) + + +__all__ = ["ApolloTracingExtension", "ApolloTracingExtensionSync"] diff --git a/strawberry/extensions/tracing/datadog.py b/strawberry/extensions/tracing/datadog.py index 3690a2ed42..2b8c676ca2 100644 --- a/strawberry/extensions/tracing/datadog.py +++ b/strawberry/extensions/tracing/datadog.py @@ -43,18 +43,20 @@ def create_span( name: str, **kwargs: Any, ) -> Span: - """ - Create a span with the given name and kwargs. + """Create a span with the given name and kwargs. + You can override this if you want to add more tags to the span. Example: + ```python class CustomExtension(DatadogTracingExtension): def create_span(self, lifecycle_step, name, **kwargs): span = super().create_span(lifecycle_step, name, **kwargs) if lifecycle_step == LifeCycleStep.OPERATION: span.set_tag("graphql.query", self.execution_context.query) return span + ``` """ return tracer.trace( name, @@ -173,3 +175,6 @@ def resolve( span.set_tag("graphql.path", ".".join(map(str, info.path.as_list()))) return _next(root, info, *args, **kwargs) + + +__all__ = ["DatadogTracingExtension", "DatadogTracingExtensionSync"] diff --git a/strawberry/extensions/tracing/opentelemetry.py b/strawberry/extensions/tracing/opentelemetry.py index 08a28fde1e..285c2e5f92 100644 --- a/strawberry/extensions/tracing/opentelemetry.py +++ b/strawberry/extensions/tracing/opentelemetry.py @@ -208,3 +208,6 @@ def resolve( result = _next(root, info, *args, **kwargs) return result + + +__all__ = ["OpenTelemetryExtension", "OpenTelemetryExtensionSync"] diff --git a/strawberry/extensions/tracing/sentry.py b/strawberry/extensions/tracing/sentry.py index 05b0228d2e..1322c91060 100644 --- a/strawberry/extensions/tracing/sentry.py +++ b/strawberry/extensions/tracing/sentry.py @@ -156,3 +156,6 @@ def resolve( span.set_tag("graphql.path", ".".join(map(str, info.path.as_list()))) return _next(root, info, *args, **kwargs) + + +__all__ = ["SentryTracingExtension", "SentryTracingExtensionSync"] diff --git a/strawberry/extensions/tracing/utils.py b/strawberry/extensions/tracing/utils.py index 04029e996a..c9bd3bcfd5 100644 --- a/strawberry/extensions/tracing/utils.py +++ b/strawberry/extensions/tracing/utils.py @@ -18,3 +18,6 @@ def should_skip_tracing(resolver: Callable[..., Any], info: GraphQLResolveInfo) or is_default_resolver(resolver) or resolver is None ) + + +__all__ = ["should_skip_tracing"] diff --git a/strawberry/extensions/utils.py b/strawberry/extensions/utils.py index d606db4ee8..f857db5eaf 100644 --- a/strawberry/extensions/utils.py +++ b/strawberry/extensions/utils.py @@ -35,3 +35,6 @@ def get_path_from_info(info: GraphQLResolveInfo) -> List[str]: path = path.prev return elements[::-1] + + +__all__ = ["is_introspection_key", "is_introspection_field", "get_path_from_info"] diff --git a/strawberry/extensions/validation_cache.py b/strawberry/extensions/validation_cache.py index 8edaa43245..6c9cc153c4 100644 --- a/strawberry/extensions/validation_cache.py +++ b/strawberry/extensions/validation_cache.py @@ -6,31 +6,31 @@ class ValidationCache(SchemaExtension): - """ - Add LRU caching the validation step during execution to improve performance. + """Add LRU caching the validation step during execution to improve performance. Example: - - >>> import strawberry - >>> from strawberry.extensions import ValidationCache - >>> - >>> schema = strawberry.Schema( - ... Query, - ... extensions=[ - ... ValidationCache(maxsize=100), - ... ] - ... ) - - Arguments: - - `maxsize: Optional[int]` - Set the maxsize of the cache. If `maxsize` is set to `None` then the - cache will grow without bound. - More info: https://docs.python.org/3/library/functools.html#functools.lru_cache - + ```python + import strawberry + from strawberry.extensions import ValidationCache + + schema = strawberry.Schema( + Query, + extensions=[ + ValidationCache(maxsize=100), + ], + ) + ``` """ def __init__(self, maxsize: Optional[int] = None) -> None: + """Initialize the ValidationCache. + + Args: + maxsize: Set the maxsize of the cache. If `maxsize` is set to `None` then the + cache will grow without bound. + + More info: https://docs.python.org/3/library/functools.html#functools.lru_cache + """ self.cached_validate_document = lru_cache(maxsize=maxsize)(validate_document) def on_validate(self) -> Iterator[None]: @@ -43,3 +43,6 @@ def on_validate(self) -> Iterator[None]: ) execution_context.errors = errors yield + + +__all__ = ["ValidationCache"] diff --git a/strawberry/fastapi/context.py b/strawberry/fastapi/context.py index 6a23a0e648..d6af1642cd 100644 --- a/strawberry/fastapi/context.py +++ b/strawberry/fastapi/context.py @@ -18,3 +18,6 @@ def __init__(self) -> None: self.request: Optional[Union[Request, WebSocket]] = None self.background_tasks: Optional[BackgroundTasks] = None self.response: Optional[Response] = None + + +__all__ = ["BaseContext"] diff --git a/strawberry/fastapi/handlers/graphql_transport_ws_handler.py b/strawberry/fastapi/handlers/graphql_transport_ws_handler.py index 62ae43fd6e..817f6996ac 100644 --- a/strawberry/fastapi/handlers/graphql_transport_ws_handler.py +++ b/strawberry/fastapi/handlers/graphql_transport_ws_handler.py @@ -15,3 +15,6 @@ async def get_context(self) -> Any: async def get_root_value(self) -> Any: return await self._get_root_value() + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/fastapi/handlers/graphql_ws_handler.py b/strawberry/fastapi/handlers/graphql_ws_handler.py index 33bdb4d444..0c43bbbd6e 100644 --- a/strawberry/fastapi/handlers/graphql_ws_handler.py +++ b/strawberry/fastapi/handlers/graphql_ws_handler.py @@ -13,3 +13,6 @@ async def get_context(self) -> Any: async def get_root_value(self) -> Any: return await self._get_root_value() + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/fastapi/router.py b/strawberry/fastapi/router.py index 147fb51fb7..ad49bb176e 100644 --- a/strawberry/fastapi/router.py +++ b/strawberry/fastapi/router.py @@ -364,3 +364,6 @@ def create_response( response.headers.raw.extend(sub_response.headers.raw) return response + + +__all__ = ["GraphQLRouter"] diff --git a/strawberry/federation/argument.py b/strawberry/federation/argument.py index ff2f4fc3b4..2268211a76 100644 --- a/strawberry/federation/argument.py +++ b/strawberry/federation/argument.py @@ -1,6 +1,6 @@ from typing import Iterable, Optional -from strawberry.arguments import StrawberryArgumentAnnotation +from strawberry.types.arguments import StrawberryArgumentAnnotation def argument( @@ -27,3 +27,6 @@ def argument( deprecation_reason=deprecation_reason, directives=directives, ) + + +__all__ = ["argument"] diff --git a/strawberry/federation/enum.py b/strawberry/federation/enum.py index 6d491d2a1e..0fdebcfedb 100644 --- a/strawberry/federation/enum.py +++ b/strawberry/federation/enum.py @@ -11,8 +11,8 @@ overload, ) -from strawberry.enum import _process_enum -from strawberry.enum import enum_value as base_enum_value +from strawberry.types.enum import _process_enum +from strawberry.types.enum import enum_value as base_enum_value if TYPE_CHECKING: from strawberry.enum import EnumType, EnumValueDefinition @@ -85,7 +85,6 @@ def enum( If name is passed, the name of the GraphQL type will be the value passed of name instead of the Enum class name. """ - from strawberry.federation.schema_directives import ( Authenticated, Inaccessible, @@ -118,3 +117,6 @@ def wrap(cls: EnumType) -> EnumType: return wrap return wrap(_cls) # pragma: no cover + + +__all__ = ["enum", "enum_value"] diff --git a/strawberry/federation/field.py b/strawberry/federation/field.py index 7bdac6f47b..35d4f34b47 100644 --- a/strawberry/federation/field.py +++ b/strawberry/federation/field.py @@ -15,15 +15,15 @@ overload, ) -from strawberry.field import field as base_field -from strawberry.unset import UNSET +from strawberry.types.field import field as base_field +from strawberry.types.unset import UNSET if TYPE_CHECKING: from typing_extensions import Literal from strawberry.extensions.field_extension import FieldExtension - from strawberry.field import _RESOLVER_TYPE, StrawberryField from strawberry.permission import BasePermission + from strawberry.types.field import _RESOLVER_TYPE, StrawberryField from .schema_directives import Override @@ -203,3 +203,6 @@ def field( extensions=extensions, graphql_type=graphql_type, ) + + +__all__ = ["field"] diff --git a/strawberry/federation/mutation.py b/strawberry/federation/mutation.py index d033d61c97..18df817b73 100644 --- a/strawberry/federation/mutation.py +++ b/strawberry/federation/mutation.py @@ -1,3 +1,5 @@ from .field import field mutation = field + +__all__ = ["mutation"] diff --git a/strawberry/federation/object_type.py b/strawberry/federation/object_type.py index cca3e05e4f..7005302370 100644 --- a/strawberry/federation/object_type.py +++ b/strawberry/federation/object_type.py @@ -12,10 +12,10 @@ ) from typing_extensions import dataclass_transform -from strawberry.field import StrawberryField -from strawberry.field import field as base_field -from strawberry.object_type import type as base_type -from strawberry.unset import UNSET +from strawberry.types.field import StrawberryField +from strawberry.types.field import field as base_field +from strawberry.types.object_type import type as base_type +from strawberry.types.unset import UNSET from .field import field @@ -369,3 +369,6 @@ def interface_object( is_interface=False, is_interface_object=True, ) + + +__all__ = ["type", "input", "interface", "interface_object"] diff --git a/strawberry/federation/scalar.py b/strawberry/federation/scalar.py index c424151312..9cb1183318 100644 --- a/strawberry/federation/scalar.py +++ b/strawberry/federation/scalar.py @@ -11,7 +11,7 @@ overload, ) -from strawberry.custom_scalar import ScalarWrapper, _process_scalar +from strawberry.types.scalar import ScalarWrapper, _process_scalar # in python 3.10+ NewType is a class if sys.version_info >= (3, 10): @@ -79,28 +79,48 @@ def scalar( ) -> Any: """Annotates a class or type as a GraphQL custom scalar. + Args: + cls: The class or type to annotate + name: The GraphQL name of the scalar + description: The description of the scalar + specified_by_url: The URL of the specification + serialize: The function to serialize the scalar + parse_value: The function to parse the value + parse_literal: The function to parse the literal + directives: The directives to apply to the scalar + authenticated: Whether to add the @authenticated directive + inaccessible: Whether to add the @inaccessible directive + policy: The list of policy names to add to the @policy directive + requires_scopes: The list of scopes to add to the @requires directive + tags: The list of tags to add to the @tag directive + + Returns: + The decorated class or type + Example usages: - >>> strawberry.federation.scalar( - >>> datetime.date, - >>> serialize=lambda value: value.isoformat(), - >>> parse_value=datetime.parse_date - >>> ) - - >>> Base64Encoded = strawberry.federation.scalar( - >>> NewType("Base64Encoded", bytes), - >>> serialize=base64.b64encode, - >>> parse_value=base64.b64decode - >>> ) - - >>> @strawberry.federation.scalar( - >>> serialize=lambda value: ",".join(value.items), - >>> parse_value=lambda value: CustomList(value.split(",")) - >>> ) - >>> class CustomList: - >>> def __init__(self, items): - >>> self.items = items + ```python + strawberry.federation.scalar( + datetime.date, + serialize=lambda value: value.isoformat(), + parse_value=datetime.parse_date, + ) + + Base64Encoded = strawberry.federation.scalar( + NewType("Base64Encoded", bytes), + serialize=base64.b64encode, + parse_value=base64.b64decode, + ) + + @strawberry.federation.scalar( + serialize=lambda value: ",".join(value.items), + parse_value=lambda value: CustomList(value.split(",")), + ) + class CustomList: + def __init__(self, items): + self.items = items + ``` """ from strawberry.federation.schema_directives import ( Authenticated, @@ -146,3 +166,6 @@ def wrap(cls: _T) -> ScalarWrapper: return wrap return wrap(cls) + + +__all__ = ["scalar"] diff --git a/strawberry/federation/schema.py b/strawberry/federation/schema.py index 4151833ee8..5ab21fcaa2 100644 --- a/strawberry/federation/schema.py +++ b/strawberry/federation/schema.py @@ -20,17 +20,17 @@ from graphql import GraphQLError from strawberry.annotation import StrawberryAnnotation -from strawberry.custom_scalar import scalar from strawberry.printer import print_schema from strawberry.schema import Schema as BaseSchema -from strawberry.type import ( +from strawberry.types.base import ( StrawberryContainer, + StrawberryObjectDefinition, WithStrawberryObjectDefinition, get_object_definition, ) from strawberry.types.info import Info -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion +from strawberry.types.scalar import scalar +from strawberry.types.union import StrawberryUnion from strawberry.utils.inspect import get_func_args from .schema_directive import StrawberryFederationSchemaDirective @@ -38,12 +38,12 @@ if TYPE_CHECKING: from graphql import ExecutionContext as GraphQLExecutionContext - from strawberry.custom_scalar import ScalarDefinition, ScalarWrapper - from strawberry.enum import EnumDefinition from strawberry.extensions import SchemaExtension from strawberry.federation.schema_directives import ComposeDirective from strawberry.schema.config import StrawberryConfig from strawberry.schema_directive import StrawberrySchemaDirective + from strawberry.types.enum import EnumDefinition + from strawberry.types.scalar import ScalarDefinition, ScalarWrapper FederationAny = scalar(NewType("_Any", object), name="_Any") # type: ignore @@ -112,7 +112,6 @@ def _get_federation_query_type( The _service field is added by default, but the _entities field is only added if the schema contains an entity type. """ - import strawberry from strawberry.tools.create_type import create_type from strawberry.tools.merge_types import merge_types @@ -181,7 +180,7 @@ def entities_resolver( get_result = partial(resolve_reference, **kwargs) else: - from strawberry.arguments import convert_argument + from strawberry.types.arguments import convert_argument config = info.schema.config scalar_registry = info.schema.schema_converter.scalar_registry @@ -209,7 +208,8 @@ def entities_resolver( def _remove_resolvable_field(self) -> None: # this might be removed when we remove support for federation 1 # or when we improve how we print the directives - from ..unset import UNSET + from strawberry.types.unset import UNSET + from .schema_directives import Key for directive in self.schema_directives_in_use: @@ -392,3 +392,6 @@ def _has_federation_keys( return any(_is_key(directive) for directive in definition.directives or []) return False + + +__all__ = ["Schema"] diff --git a/strawberry/federation/schema_directive.py b/strawberry/federation/schema_directive.py index c7309a4134..06ffe76336 100644 --- a/strawberry/federation/schema_directive.py +++ b/strawberry/federation/schema_directive.py @@ -3,9 +3,9 @@ from typing_extensions import dataclass_transform from strawberry.directive import directive_field -from strawberry.field import StrawberryField, field -from strawberry.object_type import _wrap_dataclass from strawberry.schema_directive import Location, StrawberrySchemaDirective +from strawberry.types.field import StrawberryField, field +from strawberry.types.object_type import _wrap_dataclass from strawberry.types.type_resolver import _get_fields diff --git a/strawberry/federation/schema_directives.py b/strawberry/federation/schema_directives.py index 6217f194d7..0f9232d7f3 100644 --- a/strawberry/federation/schema_directives.py +++ b/strawberry/federation/schema_directives.py @@ -3,7 +3,7 @@ from strawberry import directive_field from strawberry.schema_directive import Location, schema_directive -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET from .types import ( FieldSet, @@ -226,3 +226,21 @@ class Policy(FederationDirective): imported_from: ClassVar[ImportedFrom] = ImportedFrom( name="policy", url="https://specs.apollo.dev/federation/v2.7" ) + + +__all__ = [ + "External", + "Requires", + "Provides", + "Key", + "Shareable", + "Link", + "Tag", + "Override", + "Inaccessible", + "ComposeDirective", + "InterfaceObject", + "Authenticated", + "RequiresScopes", + "Policy", +] diff --git a/strawberry/federation/types.py b/strawberry/federation/types.py index 4a6cb19a9b..6584bc1765 100644 --- a/strawberry/federation/types.py +++ b/strawberry/federation/types.py @@ -1,7 +1,7 @@ from enum import Enum -from strawberry.custom_scalar import scalar -from strawberry.enum import enum +from strawberry.types.enum import enum +from strawberry.types.scalar import scalar FieldSet = scalar(str, name="_FieldSet") @@ -12,3 +12,6 @@ class LinkPurpose(Enum): SECURITY = "SECURITY" EXECUTION = "EXECUTION" + + +__all__ = ["FieldSet", "LinkImport", "LinkPurpose"] diff --git a/strawberry/federation/union.py b/strawberry/federation/union.py index d65b9c6f60..c61e4f5578 100644 --- a/strawberry/federation/union.py +++ b/strawberry/federation/union.py @@ -1,7 +1,7 @@ from typing import Any, Collection, Iterable, Optional, Type -from strawberry.union import StrawberryUnion -from strawberry.union import union as base_union +from strawberry.types.union import StrawberryUnion +from strawberry.types.union import union as base_union def union( @@ -15,15 +15,31 @@ def union( ) -> StrawberryUnion: """Creates a new named Union type. + Args: + name: The GraphQL name of the Union type. + types: The types that the Union can be. + (Deprecated, use `Annotated[U, strawberry.federation.union("Name")]` instead) + description: The GraphQL description of the Union type. + directives: The directives to attach to the Union type. + inaccessible: Whether the Union type is inaccessible. + tags: The federation tags to attach to the Union type. + Example usages: - >>> @strawberry.type - ... class A: ... - >>> @strawberry.type - ... class B: ... - >>> strawberry.federation.union("Name", (A, Optional[B])) - """ + ```python + import strawberry + from typing import Annotated + + @strawberry.federation.type(keys=["id"]) + class A: + id: strawberry.ID + + @strawberry.federation.type(keys=["id"]) + class B: + id: strawberry.ID + MyUnion = Annotated[A | B, strawberry.federation.union("Name", tags=["tag"])] + """ from strawberry.federation.schema_directives import Inaccessible, Tag directives = list(directives) @@ -40,3 +56,6 @@ def union( description=description, directives=directives, ) + + +__all__ = ["union"] diff --git a/strawberry/field_extensions/input_mutation.py b/strawberry/field_extensions/input_mutation.py index a47a8082e0..f251d016da 100644 --- a/strawberry/field_extensions/input_mutation.py +++ b/strawberry/field_extensions/input_mutation.py @@ -8,13 +8,13 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument from strawberry.extensions.field_extension import ( AsyncExtensionResolver, FieldExtension, SyncExtensionResolver, ) -from strawberry.field import StrawberryField +from strawberry.types.arguments import StrawberryArgument +from strawberry.types.field import StrawberryField from strawberry.utils.str_converters import capitalize_first, to_camel_case if TYPE_CHECKING: @@ -90,3 +90,6 @@ async def resolve_async( **kwargs, **vars(input_args), ) + + +__all__ = ["InputMutationExtension"] diff --git a/strawberry/file_uploads/scalars.py b/strawberry/file_uploads/scalars.py index 4dcaccf19a..680f9bd681 100644 --- a/strawberry/file_uploads/scalars.py +++ b/strawberry/file_uploads/scalars.py @@ -1,5 +1,7 @@ from typing import NewType -from ..custom_scalar import scalar +from strawberry.types.scalar import scalar Upload = scalar(NewType("Upload", bytes), parse_value=lambda x: x) + +__all__ = ["Upload"] diff --git a/strawberry/file_uploads/utils.py b/strawberry/file_uploads/utils.py index 8a1203ca5b..0fec3a2c82 100644 --- a/strawberry/file_uploads/utils.py +++ b/strawberry/file_uploads/utils.py @@ -30,3 +30,6 @@ def replace_placeholders_with_files( target_object[value_key] = file_object return operations + + +__all__ = ["replace_placeholders_with_files"] diff --git a/strawberry/flask/views.py b/strawberry/flask/views.py index 63c6ccae8d..cb773aeb2c 100644 --- a/strawberry/flask/views.py +++ b/strawberry/flask/views.py @@ -177,3 +177,9 @@ async def dispatch_request(self) -> ResponseReturnValue: # type: ignore async def render_graphql_ide(self, request: Request) -> Response: return render_template_string(self.graphql_ide_html) # type: ignore + + +__all__ = [ + "GraphQLView", + "AsyncGraphQLView", +] diff --git a/strawberry/http/__init__.py b/strawberry/http/__init__.py index dc86e7c9f8..b5fb6f5066 100644 --- a/strawberry/http/__init__.py +++ b/strawberry/http/__init__.py @@ -48,3 +48,12 @@ def parse_request_data(data: Mapping[str, Any]) -> GraphQLRequestData: variables=data.get("variables"), operation_name=data.get("operationName"), ) + + +__all__ = [ + "GraphQLHTTPResponse", + "process_result", + "GraphQLRequestData", + "parse_query_params", + "parse_request_data", +] diff --git a/strawberry/http/async_base_view.py b/strawberry/http/async_base_view.py index d5a0fd4f35..1e4b5fe7e9 100644 --- a/strawberry/http/async_base_view.py +++ b/strawberry/http/async_base_view.py @@ -136,9 +136,7 @@ async def parse_multipart(self, request: AsyncHTTPRequestAdapter) -> Dict[str, s def _handle_errors( self, errors: List[GraphQLError], response_data: GraphQLHTTPResponse ) -> None: - """ - Hook to allow custom handling of errors, used by the Sentry Integration - """ + """Hook to allow custom handling of errors, used by the Sentry Integration.""" async def run( self, @@ -213,3 +211,6 @@ async def process_result( self, request: Request, result: ExecutionResult ) -> GraphQLHTTPResponse: return process_result(result) + + +__all__ = ["AsyncBaseHTTPView"] diff --git a/strawberry/http/base.py b/strawberry/http/base.py index 8dcdeb2136..c29a52d362 100644 --- a/strawberry/http/base.py +++ b/strawberry/http/base.py @@ -68,3 +68,6 @@ def graphql_ide_html(self) -> str: replace_variables=self._ide_replace_variables, graphql_ide=self.graphql_ide, ) + + +__all__ = ["BaseView"] diff --git a/strawberry/http/exceptions.py b/strawberry/http/exceptions.py index cde6135754..d934696806 100644 --- a/strawberry/http/exceptions.py +++ b/strawberry/http/exceptions.py @@ -2,3 +2,6 @@ class HTTPException(Exception): def __init__(self, status_code: int, reason: str) -> None: self.status_code = status_code self.reason = reason + + +__all__ = ["HTTPException"] diff --git a/strawberry/http/ides.py b/strawberry/http/ides.py index a65ab54ade..d9c52fb716 100644 --- a/strawberry/http/ides.py +++ b/strawberry/http/ides.py @@ -28,3 +28,6 @@ def get_graphql_ide_html( ) return template + + +__all__ = ["get_graphql_ide_html", "GraphQL_IDE"] diff --git a/strawberry/http/sync_base_view.py b/strawberry/http/sync_base_view.py index 942e1fdec5..1a368b3302 100644 --- a/strawberry/http/sync_base_view.py +++ b/strawberry/http/sync_base_view.py @@ -151,9 +151,7 @@ def parse_http_body(self, request: SyncHTTPRequestAdapter) -> GraphQLRequestData def _handle_errors( self, errors: List[GraphQLError], response_data: GraphQLHTTPResponse ) -> None: - """ - Hook to allow custom handling of errors, used by the Sentry Integration - """ + """Hook to allow custom handling of errors, used by the Sentry Integration.""" def run( self, @@ -208,3 +206,6 @@ def process_result( self, request: Request, result: ExecutionResult ) -> GraphQLHTTPResponse: return process_result(result) + + +__all__ = ["SyncBaseHTTPView"] diff --git a/strawberry/http/temporal_response.py b/strawberry/http/temporal_response.py index 854763b553..47bf52fa9d 100644 --- a/strawberry/http/temporal_response.py +++ b/strawberry/http/temporal_response.py @@ -6,3 +6,6 @@ class TemporalResponse: status_code: int = 200 headers: Dict[str, str] = field(default_factory=dict) + + +__all__ = ["TemporalResponse"] diff --git a/strawberry/http/types.py b/strawberry/http/types.py index 1bbfbf51d6..28794c9afa 100644 --- a/strawberry/http/types.py +++ b/strawberry/http/types.py @@ -11,3 +11,6 @@ class FormData(TypedDict): files: Mapping[str, Any] form: Mapping[str, Any] + + +__all__ = ["HTTPMethod", "QueryParams", "FormData"] diff --git a/strawberry/http/typevars.py b/strawberry/http/typevars.py index f9bc77287f..a48cba848e 100644 --- a/strawberry/http/typevars.py +++ b/strawberry/http/typevars.py @@ -5,3 +5,6 @@ SubResponse = TypeVar("SubResponse") Context = TypeVar("Context") RootValue = TypeVar("RootValue") + + +__all__ = ["Request", "Response", "SubResponse", "Context", "RootValue"] diff --git a/strawberry/litestar/controller.py b/strawberry/litestar/controller.py index 950c80fc27..41a459a061 100644 --- a/strawberry/litestar/controller.py +++ b/strawberry/litestar/controller.py @@ -433,3 +433,9 @@ class _GraphQLController(GraphQLController): _GraphQLController.graphql_ide = graphql_ide_ return _GraphQLController + + +__all__ = [ + "make_graphql_controller", + "GraphQLController", +] diff --git a/strawberry/litestar/handlers/__init__.py b/strawberry/litestar/handlers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strawberry/litestar/handlers/graphql_transport_ws_handler.py b/strawberry/litestar/handlers/graphql_transport_ws_handler.py index ff0f54f284..b5aa915d08 100644 --- a/strawberry/litestar/handlers/graphql_transport_ws_handler.py +++ b/strawberry/litestar/handlers/graphql_transport_ws_handler.py @@ -55,3 +55,6 @@ async def handle_request(self) -> None: pass finally: await self.shutdown() + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/litestar/handlers/graphql_ws_handler.py b/strawberry/litestar/handlers/graphql_ws_handler.py index 6a67c9732f..d91ec4f8c3 100644 --- a/strawberry/litestar/handlers/graphql_ws_handler.py +++ b/strawberry/litestar/handlers/graphql_ws_handler.py @@ -60,3 +60,6 @@ async def handle_request(self) -> Any: for operation_id in list(self.subscriptions.keys()): await self.cleanup_operation(operation_id) + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/mutation.py b/strawberry/mutation.py deleted file mode 100644 index 29466bc82e..0000000000 --- a/strawberry/mutation.py +++ /dev/null @@ -1,8 +0,0 @@ -from functools import partial - -from .field import field - -# Mutations and subscriptions are field, we might want to separate -# things in the long run for example to provide better errors -mutation = field -subscription = partial(field, is_subscription=True) diff --git a/strawberry/parent.py b/strawberry/parent.py index 8c22f11362..f95f90b8e7 100644 --- a/strawberry/parent.py +++ b/strawberry/parent.py @@ -8,31 +8,37 @@ class StrawberryParent: ... T = TypeVar("T") Parent = Annotated[T, StrawberryParent()] -Parent.__doc__ = """Represents a parameter holding the parent resolver's value. +"""Represents a parameter holding the parent resolver's value. This can be used when defining a resolver on a type when the parent isn't expected to return the type itself. Example: ->>> import strawberry ->>> from dataclasses import dataclass ->>> ->>> @dataclass ->>> class UserRow: -... id_: str -... ->>> @strawberry.type -... class User: -... @strawberry.field -... @staticmethod -... async def name(parent: strawberry.Parent[UserRow]) -> str: -... return f"User Number {parent.id}" -... ->>> @strawberry.type ->>> class Query: -... @strawberry.field -... def user(self) -> User: -... return UserRow(id_="1234") -... +```python +import strawberry +from dataclasses import dataclass + + +@dataclass +class UserRow: + id_: str + + +@strawberry.type +class User: + @strawberry.field + @staticmethod + async def name(parent: strawberry.Parent[UserRow]) -> str: + return f"User Number {parent.id_}" + + +@strawberry.type +class Query: + @strawberry.field + def user(self) -> User: + return UserRow(id_="1234") +``` """ + +__all__ = ["Parent"] diff --git a/strawberry/permission.py b/strawberry/permission.py index 8e7dabaab1..b52fdce102 100644 --- a/strawberry/permission.py +++ b/strawberry/permission.py @@ -21,7 +21,7 @@ ) from strawberry.extensions import FieldExtension from strawberry.schema_directive import Location, StrawberrySchemaDirective -from strawberry.type import StrawberryList, StrawberryOptional +from strawberry.types.base import StrawberryList, StrawberryOptional from strawberry.utils.await_maybe import await_maybe if TYPE_CHECKING: @@ -31,13 +31,25 @@ AsyncExtensionResolver, SyncExtensionResolver, ) - from strawberry.field import StrawberryField from strawberry.types import Info + from strawberry.types.field import StrawberryField class BasePermission(abc.ABC): - """ - Base class for creating permissions + """Base class for permissions. All permissions should inherit from this class. + + Example: + + ```python + from strawberry.permission import BasePermission + + + class IsAuthenticated(BasePermission): + message = "User is not authenticated" + + def has_permission(self, source, info, **kwargs): + return info.context["user"].is_authenticated + ``` """ message: Optional[str] = None @@ -52,16 +64,39 @@ class BasePermission(abc.ABC): def has_permission( self, source: Any, info: Info, **kwargs: Any ) -> Union[bool, Awaitable[bool]]: + """Check if the permission should be accepted. + + This method should be overridden by the subclasses. + """ raise NotImplementedError( "Permission classes should override has_permission method" ) def on_unauthorized(self) -> None: - """ - Default error raising for permissions. - This can be overridden to customize the behavior. - """ + """Default error raising for permissions. + + This method can be overridden to customize the error raised when the permission is not granted. + + Example: + + ```python + from strawberry.permission import BasePermission + + + class CustomPermissionError(PermissionError): + pass + + class IsAuthenticated(BasePermission): + message = "User is not authenticated" + + def has_permission(self, source, info, **kwargs): + return info.context["user"].is_authenticated + + def on_unauthorized(self) -> None: + raise CustomPermissionError(self.message) + ``` + """ # Instantiate error class error = self.error_class(self.message or "") @@ -91,17 +126,14 @@ class AutoDirective: class PermissionExtension(FieldExtension): - """ - Handles permissions for a field - Instantiate this as a field extension with all of the permissions you want to apply + """Handles permissions for a field. - fail_silently: bool = False will return None or [] if the permission fails - instead of raising an exception. This is only valid for optional or list fields. + Instantiate this as a field extension with all of the permissions you want to apply. - NOTE: - Currently, this is automatically added to the field, when using - field.permission_classes - This is deprecated behavior, please manually add the extension to field.extensions + Note: + Currently, this is automatically added to the field, when using field.permission_classes + + This is deprecated behaviour, please manually add the extension to field.extensions """ def __init__( @@ -110,16 +142,21 @@ def __init__( use_directives: bool = True, fail_silently: bool = False, ) -> None: + """Initialize the permission extension. + + Args: + permissions: List of permissions to apply. + fail_silently: If True, return None or [] instead of raising an exception. + This is only valid for optional or list fields. + use_directives: If True, add schema directives to the field. + """ self.permissions = permissions self.fail_silently = fail_silently self.return_empty_list = False self.use_directives = use_directives def apply(self, field: StrawberryField) -> None: - """ - Applies all of the permission directives to the schema - and sets up silent permissions - """ + """Applies all of the permission directives to the schema and sets up silent permissions.""" if self.use_directives: field.directives.extend( p.schema_directive for p in self.permissions if p.schema_directive @@ -147,10 +184,7 @@ def resolve( info: Info, **kwargs: Dict[str, Any], ) -> Any: - """ - Checks if the permission should be accepted and - raises an exception if not - """ + """Checks if the permission should be accepted and raises an exception if not.""" for permission in self.permissions: if not permission.has_permission(source, info, **kwargs): return self._on_unauthorized(permission) @@ -177,11 +211,20 @@ async def resolve_async( @cached_property def supports_sync(self) -> bool: - """The Permission extension always supports async checking using await_maybe, - but only supports sync checking if there are no async permissions""" + """Whether this extension can be resolved synchronously or not. + + The Permission extension always supports async checking using await_maybe, + but only supports sync checking if there are no async permissions. + """ async_permissions = [ True for permission in self.permissions if iscoroutinefunction(permission.has_permission) ] return len(async_permissions) == 0 + + +__all__ = [ + "BasePermission", + "PermissionExtension", +] diff --git a/strawberry/printer/ast_from_value.py b/strawberry/printer/ast_from_value.py index 0adeba83d1..7242d7b9df 100644 --- a/strawberry/printer/ast_from_value.py +++ b/strawberry/printer/ast_from_value.py @@ -27,7 +27,7 @@ ) import strawberry -from strawberry.type import has_object_definition +from strawberry.types.base import has_object_definition if TYPE_CHECKING: from graphql.language import ValueNode @@ -149,3 +149,6 @@ def ast_from_value(value: Any, type_: GraphQLInputType) -> Optional[ValueNode]: # Not reachable. All possible input types have been considered. raise TypeError(f"Unexpected input type: {inspect(type_)}.") # pragma: no cover + + +__all__ = ["ast_from_value"] diff --git a/strawberry/printer/printer.py b/strawberry/printer/printer.py index f6a4541837..e48a001a53 100644 --- a/strawberry/printer/printer.py +++ b/strawberry/printer/printer.py @@ -37,11 +37,11 @@ ) from graphql.utilities.print_schema import print_type as original_print_type -from strawberry.custom_scalar import ScalarWrapper -from strawberry.enum import EnumDefinition from strawberry.schema_directive import Location, StrawberrySchemaDirective -from strawberry.type import StrawberryContainer, has_object_definition -from strawberry.unset import UNSET +from strawberry.types.base import StrawberryContainer, has_object_definition +from strawberry.types.enum import EnumDefinition +from strawberry.types.scalar import ScalarWrapper +from strawberry.types.unset import UNSET from .ast_from_value import ast_from_value @@ -55,8 +55,8 @@ ) from graphql.type.directives import GraphQLDirective - from strawberry.field import StrawberryField from strawberry.schema import BaseSchema + from strawberry.types.field import StrawberryField _T = TypeVar("_T") @@ -588,3 +588,6 @@ def _name_getter(type_: Any) -> str: ), ) ) + + +__all__ = ["print_schema"] diff --git a/strawberry/quart/views.py b/strawberry/quart/views.py index c70a9b3c84..f56a95bfd2 100644 --- a/strawberry/quart/views.py +++ b/strawberry/quart/views.py @@ -102,3 +102,6 @@ async def dispatch_request(self) -> "ResponseReturnValue": # type: ignore response=e.reason, status=e.status_code, ) + + +__all__ = ["GraphQLView"] diff --git a/strawberry/relay/exceptions.py b/strawberry/relay/exceptions.py index fe1f000e9f..4150633d8c 100644 --- a/strawberry/relay/exceptions.py +++ b/strawberry/relay/exceptions.py @@ -102,3 +102,10 @@ def exception_source(self) -> Optional[ExceptionSource]: source_finder = SourceFinder() return source_finder.find_function_from_object(cast(Callable, self.function)) + + +__all__ = [ + "NodeIDAnnotationError", + "RelayWrongAnnotationError", + "RelayWrongResolverAnnotationError", +] diff --git a/strawberry/relay/fields.py b/strawberry/relay/fields.py index 72cf500db0..45ce8648ea 100644 --- a/strawberry/relay/fields.py +++ b/strawberry/relay/fields.py @@ -29,20 +29,20 @@ from typing_extensions import Annotated, get_origin from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument, argument from strawberry.extensions.field_extension import ( AsyncExtensionResolver, FieldExtension, SyncExtensionResolver, ) -from strawberry.field import _RESOLVER_TYPE, StrawberryField, field -from strawberry.lazy_type import LazyType from strawberry.relay.exceptions import ( RelayWrongAnnotationError, RelayWrongResolverAnnotationError, ) -from strawberry.type import StrawberryList, StrawberryOptional +from strawberry.types.arguments import StrawberryArgument, argument +from strawberry.types.base import StrawberryList, StrawberryOptional +from strawberry.types.field import _RESOLVER_TYPE, StrawberryField, field from strawberry.types.fields.resolver import StrawberryResolver +from strawberry.types.lazy_type import LazyType from strawberry.utils.aio import asyncgen_to_list from strawberry.utils.typing import eval_type, is_generic_alias @@ -62,7 +62,7 @@ def apply(self, field: StrawberryField) -> None: if isinstance(field.type, StrawberryList): resolver = self.get_node_list_resolver(field) else: - resolver = self.get_node_resolver(field) + resolver = self.get_node_resolver(field) # type: ignore field.base_resolver = StrawberryResolver(resolver, type_override=field.type) @@ -81,7 +81,9 @@ async def resolve_async( # async extensions. return await retval if inspect.isawaitable(retval) else retval - def get_node_resolver(self, field: StrawberryField): # noqa: ANN201 + def get_node_resolver( + self, field: StrawberryField + ) -> Callable[[Info, GlobalID], Union[Node, None, Awaitable[Union[Node, None]]]]: type_ = field.type is_optional = isinstance(type_, StrawberryOptional) @@ -97,7 +99,9 @@ def resolver( return resolver - def get_node_list_resolver(self, field: StrawberryField): # noqa: ANN201 + def get_node_list_resolver( + self, field: StrawberryField + ) -> Callable[[Info, List[GlobalID]], Union[List[Node], Awaitable[List[Node]]]]: type_ = field.type assert isinstance(type_, StrawberryList) is_optional = isinstance(type_.of_type, StrawberryOptional) @@ -390,48 +394,66 @@ def connection( case for this is to provide a filtered iterable of nodes by using some custom filter arguments. + Args: + graphql_type: The type of the nodes in the connection. This is used to + determine the type of the edges and the node field in the connection. + resolver: The resolver for the connection. This is expected to return an + iterable of the expected node type. + name: The GraphQL name of the field. + is_subscription: Whether the field is a subscription. + description: The GraphQL description of the field. + permission_classes: The permission classes to apply to the field. + deprecation_reason: The deprecation reason of the field. + default: The default value of the field. + default_factory: The default factory of the field. + metadata: The metadata of the field. + directives: The directives to apply to the field. + extensions: The extensions to apply to the field. + init: Used only for type checking purposes. + Examples: - Annotating something like this: - - >>> @strawberry.type - >>> class X: - ... some_node: relay.Connection[SomeType] = relay.connection( - resolver=get_some_nodes, - ... description="ABC", - ... ) - ... - ... @relay.connection(relay.Connection[SomeType], description="ABC") - ... def get_some_nodes(self, age: int) -> Iterable[SomeType]: - ... ... - - Will produce a query like this: - - ``` - query { - someNode ( - before: String - after: String - first: String - after: String - age: Int - ) { - totalCount - pageInfo { - hasNextPage - hasPreviousPage - startCursor - endCursor - } - edges { - cursor - node { - id - ... - } + Annotating something like this: + + ```python + @strawberry.type + class X: + some_node: relay.Connection[SomeType] = relay.connection( + resolver=get_some_nodes, + description="ABC", + ) + + @relay.connection(relay.Connection[SomeType], description="ABC") + def get_some_nodes(self, age: int) -> Iterable[SomeType]: ... + ``` + + Will produce a query like this: + + ```graphql + query { + someNode ( + before: String + after: String + first: String + after: String + age: Int + ) { + totalCount + pageInfo { + hasNextPage + hasPreviousPage + startCursor + endCursor + } + edges { + cursor + node { + id + ... } } } - ``` + } + ``` .. _Relay connections: https://relay.dev/graphql/connections.htm @@ -454,3 +476,6 @@ def connection( if resolver is not None: f = f(resolver) return f + + +__all__ = ["node", "connection"] diff --git a/strawberry/relay/types.py b/strawberry/relay/types.py index 1dc99022f8..ee9feedcd5 100644 --- a/strawberry/relay/types.py +++ b/strawberry/relay/types.py @@ -26,14 +26,17 @@ ) from typing_extensions import Annotated, Literal, Self, TypeAlias, get_args, get_origin -from strawberry.field import field -from strawberry.lazy_type import LazyType -from strawberry.object_type import interface, type -from strawberry.private import StrawberryPrivate from strawberry.relay.exceptions import NodeIDAnnotationError -from strawberry.type import StrawberryContainer, get_object_definition +from strawberry.types.base import ( + StrawberryContainer, + StrawberryObjectDefinition, + get_object_definition, +) +from strawberry.types.field import field from strawberry.types.info import Info # noqa: TCH001 -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.lazy_type import LazyType +from strawberry.types.object_type import interface, type +from strawberry.types.private import StrawberryPrivate from strawberry.utils.aio import aenumerate, aislice, resolve_awaitable from strawberry.utils.inspect import in_async_context from strawberry.utils.typing import eval_type, is_classvar @@ -319,9 +322,14 @@ class NodeIDPrivate(StrawberryPrivate): The `Node` interface will automatically create and resolve GlobalIDs based on the field annotated with `NodeID`. e.g: - >>> @strawberry.type - ... class Fruit(Node): - ... code: NodeID[str] + ```python + import strawberry + + + @strawberry.type + class Fruit(Node): + code: NodeID[str] + ``` In this case, `code` will be used to generate a global ID in the format `Fruit:` and will be exposed as `id: GlobalID!` in the @@ -352,17 +360,20 @@ class Node: single node id. Example: + ```python + import strawberry + - >>> @strawberry.type - ... class Fruit(Node): - ... id: NodeID[int] - ... name: str - ... - ... @classmethod - ... def resolve_nodes(cls, *, info, node_ids, required=False): - ... # Return an iterable of fruits in here - ... ... + @strawberry.type + class Fruit(strawberry.relay.Node): + id: strawberry.relay.NodeID[int] + name: str + @classmethod + def resolve_nodes(cls, *, info, node_ids, required=False): + # Return an iterable of fruits in here + ... + ``` """ _id_attr: ClassVar[Optional[str]] = None @@ -467,10 +478,8 @@ def resolve_id( You can override this method to provide a custom implementation. Args: - info: - The strawberry execution info resolve the type name from - root: - The node to resolve + info: The strawberry execution info resolve the type name from. + root: The node to resolve. Returns: The resolved id (which is expected to be str) @@ -535,12 +544,9 @@ def resolve_nodes( returned as `None`. Args: - info: - The strawberry execution info resolve the type name from - node_ids: - List of node ids that should be returned - required: - If `True`, all `node_ids` requested must exist. If they don't, + info: The strawberry execution info resolve the type name from. + node_ids: List of node ids that should be returned. + required: If `True`, all `node_ids` requested must exist. If they don't, an error must be raised. If `False`, missing nodes should be returned as `None`. It only makes sense when passing a list of `node_ids`, otherwise it will should ignored. @@ -595,18 +601,14 @@ def resolve_node( a single node id. Args: - info: - The strawberry execution info resolve the type name from - node_id: - The id of the node to be retrieved - required: - if the node is required or not to exist. If not, then None + info: The strawberry execution info resolve the type name from. + node_id: The id of the node to be retrieved. + required: if the node is required or not to exist. If not, then None should be returned if it doesn't exist. Otherwise an exception should be raised. Returns: The resolved node or None if it was not found - """ retval = cls.resolve_nodes(info=info, node_ids=[node_id], required=required) @@ -629,7 +631,6 @@ class PageInfo: When paginating backwards, the cursor to continue end_cursor: When paginating forwards, the cursor to continue - """ has_next_page: bool = field( @@ -655,15 +656,10 @@ class Edge(Generic[NodeType]): A cursor for use in pagination node: The item at the end of the edge - """ - cursor: str = field( - description="A cursor for use in pagination", - ) - node: NodeType = field( - description="The item at the end of the edge", - ) + cursor: str = field(description="A cursor for use in pagination") + node: NodeType = field(description="The item at the end of the edge") @classmethod def resolve_edge(cls, node: NodeType, *, cursor: Any = None) -> Self: @@ -682,11 +678,9 @@ class Connection(Generic[NodeType]): """ - page_info: PageInfo = field( - description="Pagination data for this connection", - ) + page_info: PageInfo = field(description="Pagination data for this connection") edges: List[Edge[NodeType]] = field( - description="Contains the nodes in this connection", + description="Contains the nodes in this connection" ) @classmethod @@ -702,9 +696,11 @@ def resolve_node(cls, node: Any, *, info: Info, **kwargs: Any) -> NodeType: Args: node: The resolved node which should return an instance of this - connection's `NodeType` + connection's `NodeType`. info: - The strawberry execution info resolve the type name from + The strawberry execution info resolve the type name from. + **kwargs: + Additional arguments passed to the resolver. """ return node @@ -727,18 +723,13 @@ def resolve_connection( on `first`/`last`/`before`/`after` arguments. Args: - info: - The strawberry execution info resolve the type name from - nodes: - An iterable/iteretor of nodes to paginate - before: - Returns the items in the list that come before the specified cursor - after: - Returns the items in the list that come after the specified cursor - first: - Returns the first n items from the list - last: - Returns the items in the list that come after the specified cursor + info: The strawberry execution info resolve the type name from. + nodes: An iterable/iteretor of nodes to paginate. + before: Returns the items in the list that come before the specified cursor. + after: Returns the items in the list that come after the specified cursor. + first: Returns the first n items from the list. + last: Returns the items in the list that come after the specified cursor. + kwargs: Additional arguments passed to the resolver. Returns: The resolved `Connection` @@ -759,11 +750,9 @@ class ListConnection(Connection[NodeType]): """ - page_info: PageInfo = field( - description="Pagination data for this connection", - ) + page_info: PageInfo = field(description="Pagination data for this connection") edges: List[Edge[NodeType]] = field( - description="Contains the nodes in this connection", + description="Contains the nodes in this connection" ) @classmethod @@ -783,25 +772,19 @@ def resolve_connection( This uses the described Relay Pagination algorithm_ Args: - info: - The strawberry execution info resolve the type name from - nodes: - An iterable/iteretor of nodes to paginate - before: - Returns the items in the list that come before the specified cursor - after: - Returns the items in the list that come after the specified cursor - first: - Returns the first n items from the list - last: - Returns the items in the list that come after the specified cursor + info: The strawberry execution info resolve the type name from. + nodes: An iterable/iteretor of nodes to paginate. + before: Returns the items in the list that come before the specified cursor. + after: Returns the items in the list that come after the specified cursor. + first: Returns the first n items from the list. + last: Returns the items in the list that come after the specified cursor. + kwargs: Additional arguments passed to the resolver. Returns: The resolved `Connection` .. _Relay Pagination algorithm: https://relay.dev/graphql/connections.htm#sec-Pagination-algorithm - """ slice_metadata = SliceMetadata.from_arguments( info, @@ -949,3 +932,20 @@ async def resolver() -> Self: has_next_page=has_next_page, ), ) + + +__all__ = [ + "GlobalID", + "GlobalIDValueError", + "Node", + "NodeID", + "NodeIDAnnotationError", + "NodeIDPrivate", + "NodeIterableType", + "NodeType", + "PREFIX", + "Connection", + "Edge", + "PageInfo", + "ListConnection", +] diff --git a/strawberry/relay/utils.py b/strawberry/relay/utils.py index 55185fec93..c25bd537b0 100644 --- a/strawberry/relay/utils.py +++ b/strawberry/relay/utils.py @@ -6,8 +6,8 @@ from typing import TYPE_CHECKING, Any, Tuple, Union from typing_extensions import Self, assert_never +from strawberry.types.base import StrawberryObjectDefinition from strawberry.types.nodes import InlineFragment, Selection -from strawberry.types.types import StrawberryObjectDefinition if TYPE_CHECKING: from strawberry.types.info import Info @@ -86,6 +86,7 @@ def should_resolve_list_connection_edges(info: Info) -> bool: def _check_selection(selection: Selection) -> bool: """Recursively inspect the selection to check if the user requested to resolve the `edges` field. + Args: selection (Selection): The selection to check. @@ -187,3 +188,11 @@ def from_arguments( end=end, expected=expected, ) + + +__all__ = [ + "from_base64", + "to_base64", + "should_resolve_list_connection_edges", + "SliceMetadata", +] diff --git a/strawberry/resolvers.py b/strawberry/resolvers.py index 9e034bccf5..5eac1803d2 100644 --- a/strawberry/resolvers.py +++ b/strawberry/resolvers.py @@ -4,3 +4,6 @@ def is_default_resolver(func: Callable[..., Any]) -> bool: """Check whether the function is a default resolver or a user provided one.""" return getattr(func, "_is_default", False) + + +__all__ = ["is_default_resolver"] diff --git a/strawberry/sanic/context.py b/strawberry/sanic/context.py index 193fa52762..d828282fe8 100644 --- a/strawberry/sanic/context.py +++ b/strawberry/sanic/context.py @@ -22,3 +22,6 @@ def __getattr__(self, key: str) -> object: # type: ignore ) return super().__getitem__(key) + + +__all__ = ["StrawberrySanicContext"] diff --git a/strawberry/sanic/utils.py b/strawberry/sanic/utils.py index 5b3becc901..7c57b02664 100644 --- a/strawberry/sanic/utils.py +++ b/strawberry/sanic/utils.py @@ -10,18 +10,17 @@ def convert_request_to_files_dict(request: Request) -> Dict[str, Any]: - """ - request.files has the following format, even if only a single file is uploaded: + """Converts the request.files dictionary to a dictionary of BytesIO objects. + + `request.files` has the following format, even if only a single file is uploaded: + ```python { - 'textFile': [ - sanic.request.File( - type='text/plain', - body=b'strawberry', - name='textFile.txt' - ) + "textFile": [ + sanic.request.File(type="text/plain", body=b"strawberry", name="textFile.txt") ] } + ``` Note that the dictionary entries are lists. """ @@ -38,3 +37,6 @@ def convert_request_to_files_dict(request: Request) -> Dict[str, Any]: files_dict[field_name] = BytesIO(file_list[0].body) return files_dict + + +__all__ = ["convert_request_to_files_dict"] diff --git a/strawberry/sanic/views.py b/strawberry/sanic/views.py index fec3e861ae..6c2e97f425 100644 --- a/strawberry/sanic/views.py +++ b/strawberry/sanic/views.py @@ -72,8 +72,7 @@ class GraphQLView( AsyncBaseHTTPView[Request, HTTPResponse, TemporalResponse, Context, RootValue], HTTPMethodView, ): - """ - Class based view to handle GraphQL HTTP Requests + """Class based view to handle GraphQL HTTP Requests. Args: schema: strawberry.Schema @@ -172,3 +171,6 @@ async def get(self, request: Request) -> HTTPResponse: # type: ignore[override] return await self.run(request) except HTTPException as e: return HTTPResponse(e.reason, status=e.status_code) + + +__all__ = ["GraphQLView"] diff --git a/strawberry/scalars.py b/strawberry/scalars.py index 97a6b9290f..f87f81889a 100644 --- a/strawberry/scalars.py +++ b/strawberry/scalars.py @@ -3,13 +3,14 @@ import base64 from typing import TYPE_CHECKING, Any, Dict, NewType, Union -from .custom_scalar import scalar +from strawberry.types.scalar import scalar if TYPE_CHECKING: - from .custom_scalar import ScalarDefinition, ScalarWrapper + from strawberry.types.scalar import ScalarDefinition, ScalarWrapper ID = NewType("ID", str) +"""Represent the GraphQL `ID` scalar type.""" JSON = scalar( NewType("JSON", object), # mypy doesn't like `NewType("name", Any)` @@ -62,3 +63,6 @@ def is_scalar( return True return hasattr(annotation, "_scalar_definition") + + +__all__ = ["ID", "JSON", "Base16", "Base32", "Base64", "is_scalar"] diff --git a/strawberry/schema/base.py b/strawberry/schema/base.py index d70194e30e..da15136829 100644 --- a/strawberry/schema/base.py +++ b/strawberry/schema/base.py @@ -10,14 +10,14 @@ if TYPE_CHECKING: from graphql import GraphQLError - from strawberry.custom_scalar import ScalarDefinition from strawberry.directive import StrawberryDirective - from strawberry.enum import EnumDefinition from strawberry.schema.schema_converter import GraphQLCoreConverter from strawberry.types import ExecutionContext, ExecutionResult + from strawberry.types.base import StrawberryObjectDefinition + from strawberry.types.enum import EnumDefinition from strawberry.types.graphql import OperationType - from strawberry.types.types import StrawberryObjectDefinition - from strawberry.union import StrawberryUnion + from strawberry.types.scalar import ScalarDefinition + from strawberry.types.union import StrawberryUnion from .config import StrawberryConfig @@ -113,3 +113,6 @@ def process_errors( ) -> None: for error in errors: StrawberryLogger.error(error, execution_context) + + +__all__ = ["BaseSchema"] diff --git a/strawberry/schema/compat.py b/strawberry/schema/compat.py index e71d2379d2..2831eab78a 100644 --- a/strawberry/schema/compat.py +++ b/strawberry/schema/compat.py @@ -3,7 +3,7 @@ from typing import TYPE_CHECKING, Dict, Union from strawberry.scalars import is_scalar as is_strawberry_scalar -from strawberry.type import StrawberryType, has_object_definition +from strawberry.types.base import StrawberryType, has_object_definition # TypeGuard is only available in typing_extensions => 3.10, we don't want # to force updates to the typing_extensions package so we only use it when @@ -12,7 +12,7 @@ if TYPE_CHECKING: from typing_extensions import TypeGuard - from strawberry.custom_scalar import ScalarDefinition, ScalarWrapper + from strawberry.types.scalar import ScalarDefinition, ScalarWrapper def is_input_type(type_: Union[StrawberryType, type]) -> TypeGuard[type]: @@ -51,3 +51,13 @@ def is_graphql_generic(type_: Union[StrawberryType, type]) -> bool: return type_.is_graphql_generic return False + + +__all__ = [ + "is_input_type", + "is_interface_type", + "is_scalar", + "is_enum", + "is_schema_directive", + "is_graphql_generic", +] diff --git a/strawberry/schema/config.py b/strawberry/schema/config.py index 75e93094d4..2c5a37eb53 100644 --- a/strawberry/schema/config.py +++ b/strawberry/schema/config.py @@ -20,3 +20,6 @@ def __post_init__( ) -> None: if auto_camel_case is not None: self.name_converter.auto_camel_case = auto_camel_case + + +__all__ = ["StrawberryConfig"] diff --git a/strawberry/schema/exceptions.py b/strawberry/schema/exceptions.py index 8258debb0c..21560da738 100644 --- a/strawberry/schema/exceptions.py +++ b/strawberry/schema/exceptions.py @@ -13,3 +13,6 @@ def as_http_error_reason(self, method: str) -> str: }[self.operation_type] return f"{operation_type} are not allowed when using {method}" + + +__all__ = ["InvalidOperationTypeError"] diff --git a/strawberry/schema/execute.py b/strawberry/schema/execute.py index 737fddbb16..4dacbfcbae 100644 --- a/strawberry/schema/execute.py +++ b/strawberry/schema/execute.py @@ -277,3 +277,6 @@ def execute_sync( errors=execution_context.result.errors, extensions=extensions_runner.get_extensions_results_sync(), ) + + +__all__ = ["execute", "execute_sync"] diff --git a/strawberry/schema/name_converter.py b/strawberry/schema/name_converter.py index ae6b2ba47d..ec6d0edf2a 100644 --- a/strawberry/schema/name_converter.py +++ b/strawberry/schema/name_converter.py @@ -3,25 +3,25 @@ from typing import TYPE_CHECKING, List, Optional, Union, cast from typing_extensions import Protocol -from strawberry.custom_scalar import ScalarDefinition from strawberry.directive import StrawberryDirective -from strawberry.enum import EnumDefinition, EnumValue -from strawberry.lazy_type import LazyType from strawberry.schema_directive import StrawberrySchemaDirective -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, + StrawberryObjectDefinition, StrawberryOptional, has_object_definition, ) -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion +from strawberry.types.enum import EnumDefinition, EnumValue +from strawberry.types.lazy_type import LazyType +from strawberry.types.scalar import ScalarDefinition +from strawberry.types.union import StrawberryUnion from strawberry.utils.str_converters import capitalize_first, to_camel_case from strawberry.utils.typing import eval_type if TYPE_CHECKING: - from strawberry.arguments import StrawberryArgument - from strawberry.field import StrawberryField - from strawberry.type import StrawberryType + from strawberry.types.arguments import StrawberryArgument + from strawberry.types.base import StrawberryType + from strawberry.types.field import StrawberryField class HasGraphQLName(Protocol): @@ -184,3 +184,6 @@ def get_graphql_name(self, obj: HasGraphQLName) -> str: assert obj.python_name return self.apply_naming_config(obj.python_name) + + +__all__ = ["NameConverter"] diff --git a/strawberry/schema/schema.py b/strawberry/schema/schema.py index 32014e9d8a..62e1be8577 100644 --- a/strawberry/schema/schema.py +++ b/strawberry/schema/schema.py @@ -36,10 +36,9 @@ ) from strawberry.schema.schema_converter import GraphQLCoreConverter from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY -from strawberry.type import has_object_definition from strawberry.types import ExecutionContext +from strawberry.types.base import StrawberryObjectDefinition, has_object_definition from strawberry.types.graphql import OperationType -from strawberry.types.types import StrawberryObjectDefinition from ..printer import print_schema from . import compat @@ -51,14 +50,14 @@ from graphql import ExecutionContext as GraphQLExecutionContext from graphql import ExecutionResult as GraphQLExecutionResult - from strawberry.custom_scalar import ScalarDefinition, ScalarWrapper from strawberry.directive import StrawberryDirective - from strawberry.enum import EnumDefinition from strawberry.extensions import SchemaExtension - from strawberry.field import StrawberryField - from strawberry.type import StrawberryType from strawberry.types import ExecutionResult - from strawberry.union import StrawberryUnion + from strawberry.types.base import StrawberryType + from strawberry.types.enum import EnumDefinition + from strawberry.types.field import StrawberryField + from strawberry.types.scalar import ScalarDefinition, ScalarWrapper + from strawberry.types.union import StrawberryUnion DEFAULT_ALLOWED_OPERATION_TYPES = { OperationType.QUERY, @@ -81,10 +80,45 @@ def __init__( execution_context_class: Optional[Type[GraphQLExecutionContext]] = None, config: Optional[StrawberryConfig] = None, scalar_overrides: Optional[ - Dict[object, Union[Type, ScalarWrapper, ScalarDefinition]] + Dict[object, Union[Type, ScalarWrapper, ScalarDefinition]], ] = None, schema_directives: Iterable[object] = (), ) -> None: + """Default Schema to be to be used in a Strawberry application. + + A GraphQL Schema class used to define the structure and configuration + of GraphQL queries, mutations, and subscriptions. + + This class allows the creation of a GraphQL schema by specifying the types + for queries, mutations, and subscriptions, along with various configuration + options such as directives, extensions, and scalar overrides. + + Args: + query: The entry point for queries. + mutation: The entry point for mutations. + subscription: The entry point for subscriptions. + directives: A list of operation directives that clients can use. + The bult-in `@include` and `@skip` are included by default. + types: A list of additional types that will be included in the schema. + extensions: A list of Strawberry extensions. + execution_context_class: The execution context class. + config: The configuration for the schema. + scalar_overrides: A dictionary of overrides for scalars. + schema_directives: A list of schema directives for the schema. + + Example: + ```python + import strawberry + + + @strawberry.type + class Query: + name: str = "Patrick" + + + schema = strawberry.Schema(query=Query) + ``` + """ self.query = query self.mutation = mutation self.subscription = subscription @@ -395,7 +429,7 @@ def as_str(self) -> str: __str__ = as_str def introspect(self) -> Dict[str, Any]: - """Return the introspection query result for the current schema + """Return the introspection query result for the current schema. Raises: ValueError: If the introspection query fails due to an invalid schema @@ -405,3 +439,6 @@ def introspect(self) -> Dict[str, Any]: raise ValueError(f"Invalid Schema. Errors {introspection.errors!r}") return introspection.data + + +__all__ = ["Schema"] diff --git a/strawberry/schema/schema_converter.py b/strawberry/schema/schema_converter.py index 0210602ae7..9d19ad0345 100644 --- a/strawberry/schema/schema_converter.py +++ b/strawberry/schema/schema_converter.py @@ -44,9 +44,6 @@ from graphql.language.directive_locations import DirectiveLocation from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument, convert_arguments -from strawberry.custom_scalar import ScalarWrapper -from strawberry.enum import EnumDefinition from strawberry.exceptions import ( DuplicatedTypeName, InvalidTypeInputForUnion, @@ -55,21 +52,24 @@ ScalarAlreadyRegisteredError, UnresolvedFieldTypeError, ) -from strawberry.field import UNRESOLVED -from strawberry.lazy_type import LazyType -from strawberry.private import is_private from strawberry.schema.types.scalar import _make_scalar_type -from strawberry.type import ( +from strawberry.types.arguments import StrawberryArgument, convert_arguments +from strawberry.types.base import ( StrawberryList, + StrawberryObjectDefinition, StrawberryOptional, StrawberryType, get_object_definition, has_object_definition, ) +from strawberry.types.enum import EnumDefinition +from strawberry.types.field import UNRESOLVED from strawberry.types.info import Info -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion -from strawberry.unset import UNSET +from strawberry.types.lazy_type import LazyType +from strawberry.types.private import is_private +from strawberry.types.scalar import ScalarWrapper +from strawberry.types.union import StrawberryUnion +from strawberry.types.unset import UNSET from strawberry.utils.await_maybe import await_maybe from ..extensions.field_extension import build_field_extension_resolvers @@ -85,12 +85,12 @@ GraphQLScalarType, ) - from strawberry.custom_scalar import ScalarDefinition from strawberry.directive import StrawberryDirective - from strawberry.enum import EnumValue - from strawberry.field import StrawberryField from strawberry.schema.config import StrawberryConfig from strawberry.schema_directive import StrawberrySchemaDirective + from strawberry.types.enum import EnumValue + from strawberry.types.field import StrawberryField + from strawberry.types.scalar import ScalarDefinition FieldType = TypeVar( @@ -681,7 +681,6 @@ def _get_result( def wrap_field_extensions() -> Callable[..., Any]: """Wrap the provided field resolver with the middleware.""" - for extension in field.extensions: extension.apply(field) @@ -999,3 +998,6 @@ def validate_same_type_definition( second_origin = None raise DuplicatedTypeName(first_origin, second_origin, name) + + +__all__ = ["GraphQLCoreConverter"] diff --git a/strawberry/schema/types/base_scalars.py b/strawberry/schema/types/base_scalars.py index 3b7377df25..8e73a1383a 100644 --- a/strawberry/schema/types/base_scalars.py +++ b/strawberry/schema/types/base_scalars.py @@ -7,7 +7,7 @@ import dateutil.parser from graphql import GraphQLError -from strawberry.custom_scalar import scalar +from strawberry.types.scalar import scalar def wrap_parser(parser: Callable, type_: str) -> Callable: @@ -80,3 +80,5 @@ def _verify_void(x: None) -> None: parse_value=_verify_void, description="Represents NULL values", ) + +__all__ = ["Date", "DateTime", "Time", "Decimal", "UUID", "Void"] diff --git a/strawberry/schema/types/concrete_type.py b/strawberry/schema/types/concrete_type.py index 460f1d35b8..5507209e59 100644 --- a/strawberry/schema/types/concrete_type.py +++ b/strawberry/schema/types/concrete_type.py @@ -6,10 +6,10 @@ from graphql import GraphQLField, GraphQLInputField, GraphQLType if TYPE_CHECKING: - from strawberry.custom_scalar import ScalarDefinition - from strawberry.enum import EnumDefinition - from strawberry.types.types import StrawberryObjectDefinition - from strawberry.union import StrawberryUnion + from strawberry.types.base import StrawberryObjectDefinition + from strawberry.types.enum import EnumDefinition + from strawberry.types.scalar import ScalarDefinition + from strawberry.types.union import StrawberryUnion Field = Union[GraphQLInputField, GraphQLField] diff --git a/strawberry/schema/types/scalar.py b/strawberry/schema/types/scalar.py index 3ef47f7fda..0e89ad4476 100644 --- a/strawberry/schema/types/scalar.py +++ b/strawberry/schema/types/scalar.py @@ -12,11 +12,11 @@ GraphQLString, ) -from strawberry.custom_scalar import ScalarDefinition, scalar from strawberry.file_uploads.scalars import Upload from strawberry.relay.types import GlobalID from strawberry.scalars import ID from strawberry.schema.types import base_scalars +from strawberry.types.scalar import ScalarDefinition, scalar def _make_scalar_type(definition: ScalarDefinition) -> GraphQLScalarType: @@ -78,3 +78,10 @@ def _get_scalar_definition(scalar: Type) -> ScalarDefinition: ) ), } + +__all__ = [ + "DEFAULT_SCALAR_REGISTRY", + "_get_scalar_definition", + "_make_scalar_definition", + "_make_scalar_type", +] diff --git a/strawberry/schema/validation_rules/one_of.py b/strawberry/schema/validation_rules/one_of.py index 435facae2b..eca1e4a9ff 100644 --- a/strawberry/schema/validation_rules/one_of.py +++ b/strawberry/schema/validation_rules/one_of.py @@ -78,3 +78,6 @@ def validate_one_of(self, node: ObjectValueNode, type: GraphQLNamedType) -> None nodes=[node], ) ) + + +__all__ = ["OneOfInputValidationRule"] diff --git a/strawberry/schema_codegen/__init__.py b/strawberry/schema_codegen/__init__.py index 02105589d9..5ce5c1de11 100644 --- a/strawberry/schema_codegen/__init__.py +++ b/strawberry/schema_codegen/__init__.py @@ -802,3 +802,6 @@ def codegen(schema: str) -> str: module = cst.Module(body=body) # type: ignore return module.code + + +__all__ = ["codegen"] diff --git a/strawberry/schema_directive.py b/strawberry/schema_directive.py index 3d23a18774..f519a7a766 100644 --- a/strawberry/schema_directive.py +++ b/strawberry/schema_directive.py @@ -3,11 +3,11 @@ from typing import Callable, List, Optional, Type, TypeVar from typing_extensions import dataclass_transform -from strawberry.object_type import _wrap_dataclass +from strawberry.types.field import StrawberryField, field +from strawberry.types.object_type import _wrap_dataclass from strawberry.types.type_resolver import _get_fields from .directive import directive_field -from .field import StrawberryField, field class Location(Enum): diff --git a/strawberry/starlite/controller.py b/strawberry/starlite/controller.py index 2f3d76f462..3376b1782b 100644 --- a/strawberry/starlite/controller.py +++ b/strawberry/starlite/controller.py @@ -382,3 +382,6 @@ def pick_preferred_protocol(self, socket: WebSocket) -> Optional[str]: ) return GraphQLController + + +__all__ = ["make_graphql_controller"] diff --git a/strawberry/starlite/handlers/__init__.py b/strawberry/starlite/handlers/__init__.py new file mode 100644 index 0000000000..e69de29bb2 diff --git a/strawberry/starlite/handlers/graphql_transport_ws_handler.py b/strawberry/starlite/handlers/graphql_transport_ws_handler.py index 84bdb19b04..5d65671831 100644 --- a/strawberry/starlite/handlers/graphql_transport_ws_handler.py +++ b/strawberry/starlite/handlers/graphql_transport_ws_handler.py @@ -54,3 +54,6 @@ async def handle_request(self) -> None: pass finally: await self.shutdown() + + +__all__ = ["GraphQLTransportWSHandler"] diff --git a/strawberry/starlite/handlers/graphql_ws_handler.py b/strawberry/starlite/handlers/graphql_ws_handler.py index 47ddcb3088..237ac95e14 100644 --- a/strawberry/starlite/handlers/graphql_ws_handler.py +++ b/strawberry/starlite/handlers/graphql_ws_handler.py @@ -59,3 +59,6 @@ async def handle_request(self) -> Any: for operation_id in list(self.subscriptions.keys()): await self.cleanup_operation(operation_id) + + +__all__ = ["GraphQLWSHandler"] diff --git a/strawberry/subscriptions/__init__.py b/strawberry/subscriptions/__init__.py index 61a8c08f9f..7d38a1a90a 100644 --- a/strawberry/subscriptions/__init__.py +++ b/strawberry/subscriptions/__init__.py @@ -1,2 +1,8 @@ GRAPHQL_TRANSPORT_WS_PROTOCOL = "graphql-transport-ws" GRAPHQL_WS_PROTOCOL = "graphql-ws" + + +__all__ = [ + "GRAPHQL_TRANSPORT_WS_PROTOCOL", + "GRAPHQL_WS_PROTOCOL", +] diff --git a/strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py b/strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py index 1368214127..c17c6ee143 100644 --- a/strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py +++ b/strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py @@ -1,2 +1,7 @@ # Code 4406 is "Subprotocol not acceptable" WS_4406_PROTOCOL_NOT_ACCEPTABLE = 4406 + + +__all__ = [ + "WS_4406_PROTOCOL_NOT_ACCEPTABLE", +] diff --git a/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py b/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py index f20c674124..fa0cb7c177 100644 --- a/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +++ b/strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py @@ -30,7 +30,7 @@ SubscribeMessagePayload, ) from strawberry.types.graphql import OperationType -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET from strawberry.utils.debug import pretty_print_graphql_operation from strawberry.utils.operation import get_operation_type @@ -66,23 +66,23 @@ def __init__( @abstractmethod async def get_context(self) -> Any: - """Return the operations context""" + """Return the operations context.""" @abstractmethod async def get_root_value(self) -> Any: - """Return the schemas root value""" + """Return the schemas root value.""" @abstractmethod async def send_json(self, data: dict) -> None: - """Send the data JSON encoded to the WebSocket client""" + """Send the data JSON encoded to the WebSocket client.""" @abstractmethod async def close(self, code: int, reason: str) -> None: - """Close the WebSocket with the passed code and reason""" + """Close the WebSocket with the passed code and reason.""" @abstractmethod async def handle_request(self) -> Any: - """Handle the request this instance was created for""" + """Handle the request this instance was created for.""" async def handle(self) -> Any: return await self.handle_request() @@ -286,10 +286,7 @@ async def get_result_source() -> AsyncIterator[ExecutionResult]: async def operation_task( self, result_source: AsyncGenerator, operation: Operation ) -> None: - """ - Operation task top level method. Cleans up and de-registers the operation - once it is done. - """ + """The operation task's top level method. Cleans-up and de-registers the operation once it is done.""" # TODO: Handle errors in this method using self.handle_task_exception() try: await self.handle_async_results(result_source, operation) @@ -371,9 +368,7 @@ async def cleanup_operation(self, operation_id: str) -> None: # websocket handler Task. async def reap_completed_tasks(self) -> None: - """ - Await tasks that have completed - """ + """Await tasks that have completed.""" tasks, self.completed_tasks = self.completed_tasks, [] for task in tasks: with suppress(BaseException): @@ -381,10 +376,7 @@ async def reap_completed_tasks(self) -> None: class Operation: - """ - A class encapsulating a single operation with its id. - Helps enforce protocol state transition. - """ + """A class encapsulating a single operation with its id. Helps enforce protocol state transition.""" __slots__ = ["handler", "id", "operation_type", "completed", "task"] @@ -408,3 +400,6 @@ async def send_message(self, message: GraphQLTransportMessage) -> None: # de-register the operation _before_ sending the final message self.handler.forget_id(self.id) await self.handler.send_message(message) + + +__all__ = ["BaseGraphQLTransportWSHandler", "Operation"] diff --git a/strawberry/subscriptions/protocols/graphql_transport_ws/types.py b/strawberry/subscriptions/protocols/graphql_transport_ws/types.py index c982ccc463..76260fabee 100644 --- a/strawberry/subscriptions/protocols/graphql_transport_ws/types.py +++ b/strawberry/subscriptions/protocols/graphql_transport_ws/types.py @@ -3,7 +3,7 @@ from dataclasses import asdict, dataclass from typing import TYPE_CHECKING, Any, Dict, List, Optional -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET if TYPE_CHECKING: from graphql import GraphQLFormattedError @@ -21,9 +21,7 @@ def as_dict(self) -> dict: @dataclass class ConnectionInitMessage(GraphQLTransportMessage): - """ - Direction: Client -> Server - """ + """Direction: Client -> Server.""" payload: Optional[Dict[str, Any]] = UNSET type: str = "connection_init" @@ -31,9 +29,7 @@ class ConnectionInitMessage(GraphQLTransportMessage): @dataclass class ConnectionAckMessage(GraphQLTransportMessage): - """ - Direction: Server -> Client - """ + """Direction: Server -> Client.""" payload: Optional[Dict[str, Any]] = UNSET type: str = "connection_ack" @@ -41,9 +37,7 @@ class ConnectionAckMessage(GraphQLTransportMessage): @dataclass class PingMessage(GraphQLTransportMessage): - """ - Direction: bidirectional - """ + """Direction: bidirectional.""" payload: Optional[Dict[str, Any]] = UNSET type: str = "ping" @@ -51,9 +45,7 @@ class PingMessage(GraphQLTransportMessage): @dataclass class PongMessage(GraphQLTransportMessage): - """ - Direction: bidirectional - """ + """Direction: bidirectional.""" payload: Optional[Dict[str, Any]] = UNSET type: str = "pong" @@ -69,9 +61,7 @@ class SubscribeMessagePayload: @dataclass class SubscribeMessage(GraphQLTransportMessage): - """ - Direction: Client -> Server - """ + """Direction: Client -> Server.""" id: str payload: SubscribeMessagePayload @@ -80,9 +70,7 @@ class SubscribeMessage(GraphQLTransportMessage): @dataclass class NextMessage(GraphQLTransportMessage): - """ - Direction: Server -> Client - """ + """Direction: Server -> Client.""" id: str payload: Dict[str, Any] # TODO: shape like FormattedExecutionResult @@ -94,9 +82,7 @@ def as_dict(self) -> dict: @dataclass class ErrorMessage(GraphQLTransportMessage): - """ - Direction: Server -> Client - """ + """Direction: Server -> Client.""" id: str payload: List[GraphQLFormattedError] @@ -105,9 +91,19 @@ class ErrorMessage(GraphQLTransportMessage): @dataclass class CompleteMessage(GraphQLTransportMessage): - """ - Direction: bidirectional - """ + """Direction: bidirectional.""" id: str type: str = "complete" + + +__all__ = [ + "ConnectionInitMessage", + "ConnectionAckMessage", + "PingMessage", + "PongMessage", + "SubscribeMessage", + "NextMessage", + "ErrorMessage", + "CompleteMessage", +] diff --git a/strawberry/subscriptions/protocols/graphql_ws/__init__.py b/strawberry/subscriptions/protocols/graphql_ws/__init__.py index 8b884cf45f..2b3696e822 100644 --- a/strawberry/subscriptions/protocols/graphql_ws/__init__.py +++ b/strawberry/subscriptions/protocols/graphql_ws/__init__.py @@ -8,3 +8,17 @@ GQL_ERROR = "error" GQL_COMPLETE = "complete" GQL_STOP = "stop" + + +__all__ = [ + "GQL_CONNECTION_INIT", + "GQL_CONNECTION_ACK", + "GQL_CONNECTION_ERROR", + "GQL_CONNECTION_TERMINATE", + "GQL_CONNECTION_KEEP_ALIVE", + "GQL_START", + "GQL_DATA", + "GQL_ERROR", + "GQL_COMPLETE", + "GQL_STOP", +] diff --git a/strawberry/subscriptions/protocols/graphql_ws/handlers.py b/strawberry/subscriptions/protocols/graphql_ws/handlers.py index c4863ff49e..23a15f67af 100644 --- a/strawberry/subscriptions/protocols/graphql_ws/handlers.py +++ b/strawberry/subscriptions/protocols/graphql_ws/handlers.py @@ -51,23 +51,23 @@ def __init__( @abstractmethod async def get_context(self) -> Any: - """Return the operations context""" + """Return the operations context.""" @abstractmethod async def get_root_value(self) -> Any: - """Return the schemas root value""" + """Return the schemas root value.""" @abstractmethod async def send_json(self, data: OperationMessage) -> None: - """Send the data JSON encoded to the WebSocket client""" + """Send the data JSON encoded to the WebSocket client.""" @abstractmethod async def close(self, code: int = 1000, reason: Optional[str] = None) -> None: - """Close the WebSocket with the passed code and reason""" + """Close the WebSocket with the passed code and reason.""" @abstractmethod async def handle_request(self) -> Any: - """Handle the request this instance was created for""" + """Handle the request this instance was created for.""" async def handle(self) -> Any: return await self.handle_request() @@ -208,3 +208,6 @@ async def send_message( if payload is not None: data["payload"] = payload await self.send_json(data) + + +__all__ = ["BaseGraphQLWSHandler"] diff --git a/strawberry/subscriptions/protocols/graphql_ws/types.py b/strawberry/subscriptions/protocols/graphql_ws/types.py index abd0ce785e..4b7d35d278 100644 --- a/strawberry/subscriptions/protocols/graphql_ws/types.py +++ b/strawberry/subscriptions/protocols/graphql_ws/types.py @@ -38,3 +38,14 @@ class OperationMessage(TypedDict, total=False): type: str id: str payload: OperationMessagePayload + + +__all__ = [ + "ConnectionInitPayload", + "ConnectionErrorPayload", + "StartPayload", + "DataPayload", + "ErrorPayload", + "OperationMessagePayload", + "OperationMessage", +] diff --git a/strawberry/test/client.py b/strawberry/test/client.py index abbe678135..9127799763 100644 --- a/strawberry/test/client.py +++ b/strawberry/test/client.py @@ -91,47 +91,59 @@ def _build_body( def _build_multipart_file_map( variables: Dict[str, Mapping], files: Dict[str, object] ) -> Dict[str, List[str]]: - """Creates the file mapping between the variables and the files objects passed - as key arguments + """Creates the file mapping between the variables and the files objects passed as key arguments. + + Args: + variables: A dictionary with the variables that are going to be passed to the + query. + files: A dictionary with the files that are going to be passed to the query. Example usages: - >>> _build_multipart_file_map( - >>> variables={"textFile": None}, files={"textFile": f} - >>> ) - ... {"textFile": ["variables.textFile"]} + ```python + _build_multipart_file_map(variables={"textFile": None}, files={"textFile": f}) + # {"textFile": ["variables.textFile"]} + ``` If the variable is a list we have to enumerate files in the mapping - >>> _build_multipart_file_map( - >>> variables={"files": [None, None]}, - >>> files={"file1": file1, "file2": file2}, - >>> ) - ... {"file1": ["variables.files.0"], "file2": ["variables.files.1"]} + + ```python + _build_multipart_file_map( + variables={"files": [None, None]}, + files={"file1": file1, "file2": file2}, + ) + # {"file1": ["variables.files.0"], "file2": ["variables.files.1"]} + ``` If `variables` contains another keyword (a folder) we must include that keyword in the mapping - >>> _build_multipart_file_map( - >>> variables={"folder": {"files": [None, None]}}, - >>> files={"file1": file1, "file2": file2}, - >>> ) - ... { - ... "file1": ["variables.files.folder.files.0"], - ... "file2": ["variables.files.folder.files.1"] - ... } + + ```python + _build_multipart_file_map( + variables={"folder": {"files": [None, None]}}, + files={"file1": file1, "file2": file2}, + ) + # { + # "file1": ["variables.files.folder.files.0"], + # "file2": ["variables.files.folder.files.1"] + # } + ``` If `variables` includes both a list of files and other single values, we must map them accordingly - >>> _build_multipart_file_map( - >>> variables={"files": [None, None], "textFile": None}, - >>> files={"file1": file1, "file2": file2, "textFile": file3}, - >>> ) - ... { - ... "file1": ["variables.files.0"], - ... "file2": ["variables.files.1"], - ... "textFile": ["variables.textFile"], - ... } - """ + ```python + _build_multipart_file_map( + variables={"files": [None, None], "textFile": None}, + files={"file1": file1, "file2": file2, "textFile": file3}, + ) + # { + # "file1": ["variables.files.0"], + # "file2": ["variables.files.1"], + # "textFile": ["variables.textFile"], + # } + ``` + """ map: Dict[str, List[str]] = {} for key, values in variables.items(): reference = key @@ -167,3 +179,6 @@ def _decode(self, response: Any, type: Literal["multipart", "json"]) -> Any: if type == "multipart": return json.loads(response.content.decode()) return response.json() + + +__all__ = ["BaseGraphQLTestClient", "Response", "Body"] diff --git a/strawberry/tools/create_type.py b/strawberry/tools/create_type.py index 2ba4d17c21..8436a5969c 100644 --- a/strawberry/tools/create_type.py +++ b/strawberry/tools/create_type.py @@ -2,7 +2,7 @@ from typing import List, Optional, Sequence, Type import strawberry -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField def create_type( @@ -14,15 +14,31 @@ def create_type( directives: Optional[Sequence[object]] = (), extend: bool = False, ) -> Type: - """Create a Strawberry type from a list of StrawberryFields + """Create a Strawberry type from a list of StrawberryFields. - >>> @strawberry.field - >>> def hello(info) -> str: - >>> return "World" - >>> - >>> Query = create_type(name="Query", fields=[hello]) - """ + Args: + name: The GraphQL name of the type. + fields: The fields of the type. + is_input: Whether the type is an input type. + is_interface: Whether the type is an interface. + description: The GraphQL description of the type. + directives: The directives to attach to the type. + extend: Whether the type is an extension. + + Example usage: + + ```python + import strawberry + + + @strawberry.field + def hello(info) -> str: + return "World" + + Query = create_type(name="Query", fields=[hello]) + ``` + """ if not fields: raise ValueError(f'Can\'t create type "{name}" with no fields') @@ -55,3 +71,6 @@ def create_type( directives=directives, extend=extend, ) + + +__all__ = ["create_type"] diff --git a/strawberry/tools/merge_types.py b/strawberry/tools/merge_types.py index 4dea67b3fc..84095d7086 100644 --- a/strawberry/tools/merge_types.py +++ b/strawberry/tools/merge_types.py @@ -4,11 +4,11 @@ from typing import Tuple import strawberry -from strawberry.type import has_object_definition +from strawberry.types.base import has_object_definition def merge_types(name: str, types: Tuple[type, ...]) -> type: - """Merge multiple Strawberry types into one + """Merge multiple Strawberry types into one. For example, given two queries `A` and `B`, one can merge them into a super type as follows: @@ -20,7 +20,6 @@ def merge_types(name: str, types: Tuple[type, ...]) -> type: class SuperQuery(B, A): ... """ - if not types: raise ValueError("Can't merge types if none are supplied") @@ -35,3 +34,6 @@ class SuperQuery(B, A): ) return strawberry.type(type(name, types, {})) + + +__all__ = ["merge_types"] diff --git a/strawberry/type.py b/strawberry/type.py deleted file mode 100644 index b9a2b595e6..0000000000 --- a/strawberry/type.py +++ /dev/null @@ -1,232 +0,0 @@ -from __future__ import annotations - -from abc import ABC, abstractmethod -from typing import ( - TYPE_CHECKING, - Any, - ClassVar, - List, - Mapping, - Optional, - Type, - TypeVar, - Union, - overload, -) -from typing_extensions import Literal, Protocol, Self - -from strawberry.utils.typing import is_concrete_generic - -if TYPE_CHECKING: - from typing_extensions import TypeGuard - - from strawberry.types.types import StrawberryObjectDefinition - - -class StrawberryType(ABC): - """ - Every type that is decorated by strawberry should have a dunder - `__strawberry_definition__` with instance of a StrawberryType that contains - the parsed information that strawberry created. - - NOTE: ATM this is only true for @type @interface @input follow https://github.com/strawberry-graphql/strawberry/issues/2841 - to see progress. - """ - - @property - def type_params(self) -> List[TypeVar]: - return [] - - @property - def is_one_of(self) -> bool: - return False - - @abstractmethod - def copy_with( - self, - type_var_map: Mapping[ - str, Union[StrawberryType, Type[WithStrawberryObjectDefinition]] - ], - ) -> Union[StrawberryType, Type[WithStrawberryObjectDefinition]]: - raise NotImplementedError() - - @property - @abstractmethod - def is_graphql_generic(self) -> bool: - raise NotImplementedError() - - def has_generic(self, type_var: TypeVar) -> bool: - return False - - def __eq__(self, other: object) -> bool: - from strawberry.annotation import StrawberryAnnotation - - if isinstance(other, StrawberryType): - return self is other - - elif isinstance(other, StrawberryAnnotation): - return self == other.resolve() - - else: - # This could be simplified if StrawberryAnnotation.resolve() always returned - # a StrawberryType - resolved = StrawberryAnnotation(other).resolve() - if isinstance(resolved, StrawberryType): - return self == resolved - else: - return NotImplemented - - def __hash__(self) -> int: - # TODO: Is this a bad idea? __eq__ objects are supposed to have the same hash - return id(self) - - -class StrawberryContainer(StrawberryType): - def __init__( - self, of_type: Union[StrawberryType, Type[WithStrawberryObjectDefinition], type] - ) -> None: - self.of_type = of_type - - def __hash__(self) -> int: - return hash((self.__class__, self.of_type)) - - def __eq__(self, other: object) -> bool: - if isinstance(other, StrawberryType): - if isinstance(other, StrawberryContainer): - return self.of_type == other.of_type - else: - return False - - return super().__eq__(other) - - @property - def type_params(self) -> List[TypeVar]: - if has_object_definition(self.of_type): - parameters = getattr(self.of_type, "__parameters__", None) - - return list(parameters) if parameters else [] - - elif isinstance(self.of_type, StrawberryType): - return self.of_type.type_params - - else: - return [] - - def copy_with( - self, - type_var_map: Mapping[ - str, Union[StrawberryType, Type[WithStrawberryObjectDefinition]] - ], - ) -> Self: - of_type_copy = self.of_type - - if has_object_definition(self.of_type): - type_definition = self.of_type.__strawberry_definition__ - - if type_definition.is_graphql_generic: - of_type_copy = type_definition.copy_with(type_var_map) - - elif ( - isinstance(self.of_type, StrawberryType) and self.of_type.is_graphql_generic - ): - of_type_copy = self.of_type.copy_with(type_var_map) - - return type(self)(of_type_copy) - - @property - def is_graphql_generic(self) -> bool: - from strawberry.schema.compat import is_graphql_generic - - type_ = self.of_type - - return is_graphql_generic(type_) - - def has_generic(self, type_var: TypeVar) -> bool: - if isinstance(self.of_type, StrawberryType): - return self.of_type.has_generic(type_var) - return False - - -class StrawberryList(StrawberryContainer): ... - - -class StrawberryOptional(StrawberryContainer): ... - - -class StrawberryTypeVar(StrawberryType): - def __init__(self, type_var: TypeVar) -> None: - self.type_var = type_var - - def copy_with( - self, type_var_map: Mapping[str, Union[StrawberryType, type]] - ) -> Union[StrawberryType, type]: - return type_var_map[self.type_var.__name__] - - @property - def is_graphql_generic(self) -> bool: - return True - - def has_generic(self, type_var: TypeVar) -> bool: - return self.type_var == type_var - - @property - def type_params(self) -> List[TypeVar]: - return [self.type_var] - - def __eq__(self, other: object) -> bool: - if isinstance(other, StrawberryTypeVar): - return self.type_var == other.type_var - if isinstance(other, TypeVar): - return self.type_var == other - - return super().__eq__(other) - - def __hash__(self) -> int: - return hash(self.type_var) - - -class WithStrawberryObjectDefinition(Protocol): - __strawberry_definition__: ClassVar[StrawberryObjectDefinition] - - -def has_object_definition( - obj: Any, -) -> TypeGuard[Type[WithStrawberryObjectDefinition]]: - if hasattr(obj, "__strawberry_definition__"): - return True - # TODO: Generics remove dunder members here, so we inject it here. - # Would be better to avoid it somehow. - # https://github.com/python/cpython/blob/3a314f7c3df0dd7c37da7d12b827f169ee60e1ea/Lib/typing.py#L1152 - if is_concrete_generic(obj): - concrete = obj.__origin__ - if hasattr(concrete, "__strawberry_definition__"): - obj.__strawberry_definition__ = concrete.__strawberry_definition__ - return True - return False - - -@overload -def get_object_definition( - obj: Any, - *, - strict: Literal[True], -) -> StrawberryObjectDefinition: ... - - -@overload -def get_object_definition( - obj: Any, - *, - strict: bool = False, -) -> Optional[StrawberryObjectDefinition]: ... - - -def get_object_definition( - obj: Any, - *, - strict: bool = False, -) -> Optional[StrawberryObjectDefinition]: - definition = obj.__strawberry_definition__ if has_object_definition(obj) else None - if strict and definition is None: - raise TypeError(f"{obj!r} does not have a StrawberryObjectDefinition") - return definition diff --git a/strawberry/types/__init__.py b/strawberry/types/__init__.py index 0187701c58..1de5482d7e 100644 --- a/strawberry/types/__init__.py +++ b/strawberry/types/__init__.py @@ -1,4 +1,11 @@ +from .base import get_object_definition, has_object_definition from .execution import ExecutionContext, ExecutionResult from .info import Info -__all__ = ["ExecutionContext", "ExecutionResult", "Info"] +__all__ = [ + "ExecutionContext", + "ExecutionResult", + "Info", + "get_object_definition", + "has_object_definition", +] diff --git a/strawberry/arguments.py b/strawberry/types/arguments.py similarity index 82% rename from strawberry/arguments.py rename to strawberry/types/arguments.py index ee32fe36f8..a48f0e417d 100644 --- a/strawberry/arguments.py +++ b/strawberry/types/arguments.py @@ -16,25 +16,28 @@ from typing_extensions import Annotated, get_args, get_origin from strawberry.annotation import StrawberryAnnotation -from strawberry.enum import EnumDefinition -from strawberry.lazy_type import LazyType, StrawberryLazyReference -from strawberry.type import StrawberryList, StrawberryOptional, has_object_definition - -from .exceptions import MultipleStrawberryArgumentsError, UnsupportedTypeError -from .scalars import is_scalar -from .unset import UNSET as _deprecated_UNSET -from .unset import _deprecated_is_unset # noqa # type: ignore +from strawberry.exceptions import MultipleStrawberryArgumentsError, UnsupportedTypeError +from strawberry.scalars import is_scalar +from strawberry.types.base import ( + StrawberryList, + StrawberryOptional, + has_object_definition, +) +from strawberry.types.enum import EnumDefinition +from strawberry.types.lazy_type import LazyType, StrawberryLazyReference +from strawberry.types.unset import UNSET as _deprecated_UNSET +from strawberry.types.unset import _deprecated_is_unset # noqa # type: ignore if TYPE_CHECKING: - from strawberry.custom_scalar import ScalarDefinition, ScalarWrapper from strawberry.schema.config import StrawberryConfig - from strawberry.type import StrawberryType + from strawberry.types.base import StrawberryType + from strawberry.types.scalar import ScalarDefinition, ScalarWrapper DEPRECATED_NAMES: Dict[str, str] = { "UNSET": ( "importing `UNSET` from `strawberry.arguments` is deprecated, " - "import instead from `strawberry` or from `strawberry.unset`" + "import instead from `strawberry` or from `strawberry.types.unset`" ), "is_unset": "`is_unset` is deprecated use `value is UNSET` instead", } @@ -202,8 +205,8 @@ def convert_arguments( """Converts a nested dictionary to a dictionary of actual types. It deals with conversion of input types to proper dataclasses and - also uses a sentinel value for unset values.""" - + also uses a sentinel value for unset values. + """ if not arguments: return {} @@ -234,6 +237,34 @@ def argument( directives: Iterable[object] = (), metadata: Optional[Mapping[Any, Any]] = None, ) -> StrawberryArgumentAnnotation: + """Function to add metadata to an argument, like a description or deprecation reason. + + Args: + description: The GraphQL description of the argument + name: The GraphQL name of the argument + deprecation_reason: The reason why this argument is deprecated, + setting this will mark the argument as deprecated + directives: The directives to attach to the argument + metadata: Metadata to attach to the argument, this can be used + to store custom data that can be used by custom logic or plugins + + Returns: + A StrawberryArgumentAnnotation object that can be used to customise an argument + + Example: + ```python + import strawberry + + + @strawberry.type + class Query: + @strawberry.field + def example( + self, info, value: int = strawberry.argument(description="The value") + ) -> int: + return value + ``` + """ return StrawberryArgumentAnnotation( description=description, name=name, diff --git a/strawberry/auto.py b/strawberry/types/auto.py similarity index 84% rename from strawberry/auto.py rename to strawberry/types/auto.py index 5198047c4b..9de85b1e34 100644 --- a/strawberry/auto.py +++ b/strawberry/types/auto.py @@ -3,9 +3,8 @@ from typing import Any, Optional, Union, cast from typing_extensions import Annotated, get_args, get_origin -from strawberry.type import StrawberryType - -from .annotation import StrawberryAnnotation +from strawberry.annotation import StrawberryAnnotation +from strawberry.types.base import StrawberryType class StrawberryAutoMeta(type): @@ -77,3 +76,22 @@ def __repr__(self) -> str: auto = Annotated[Any, StrawberryAuto()] +"""Special marker for automatic annotation. + +A special value that can be used to automatically infer the type of a field +when using integrations like Strawberry Django or Strawberry Pydantic. + +Example: +```python +import strawberry + +from my_user_app import models + + +@strawberry.django.type(models.User) +class User: + name: strawberry.auto +``` +""" + +__all__ = ["auto"] diff --git a/strawberry/types/types.py b/strawberry/types/base.py similarity index 54% rename from strawberry/types/types.py rename to strawberry/types/base.py index d028291a1b..9c235093d7 100644 --- a/strawberry/types/types.py +++ b/strawberry/types/base.py @@ -1,10 +1,12 @@ from __future__ import annotations import dataclasses +from abc import ABC, abstractmethod from typing import ( TYPE_CHECKING, Any, Callable, + ClassVar, Dict, List, Mapping, @@ -13,29 +15,237 @@ Type, TypeVar, Union, + overload, ) -from typing_extensions import Self, deprecated +from typing_extensions import Literal, Protocol, Self, deprecated -from strawberry.type import ( - StrawberryList, - StrawberryType, - StrawberryTypeVar, - WithStrawberryObjectDefinition, -) from strawberry.utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor from strawberry.utils.inspect import get_specialized_type_var_map +from strawberry.utils.typing import is_concrete_generic from strawberry.utils.typing import is_generic as is_type_generic if TYPE_CHECKING: + from typing_extensions import TypeGuard + from graphql import GraphQLAbstractType, GraphQLResolveInfo - from strawberry.field import StrawberryField + from strawberry.types.field import StrawberryField + + +class StrawberryType(ABC): + """The base class for all types that Strawberry uses. + + Every type that is decorated by strawberry should have a dunder + `__strawberry_definition__` with an instance of a StrawberryType that contains + the parsed information that strawberry created. + + NOTE: ATM this is only true for @type @interface @input follow + https://github.com/strawberry-graphql/strawberry/issues/2841 to see progress. + """ + + @property + def type_params(self) -> List[TypeVar]: + return [] + + @property + def is_one_of(self) -> bool: + return False + + @abstractmethod + def copy_with( + self, + type_var_map: Mapping[ + str, Union[StrawberryType, Type[WithStrawberryObjectDefinition]] + ], + ) -> Union[StrawberryType, Type[WithStrawberryObjectDefinition]]: + raise NotImplementedError() + + @property + @abstractmethod + def is_graphql_generic(self) -> bool: + raise NotImplementedError() + + def has_generic(self, type_var: TypeVar) -> bool: + return False + + def __eq__(self, other: object) -> bool: + from strawberry.annotation import StrawberryAnnotation + + if isinstance(other, StrawberryType): + return self is other + + elif isinstance(other, StrawberryAnnotation): + return self == other.resolve() + + else: + # This could be simplified if StrawberryAnnotation.resolve() always returned + # a StrawberryType + resolved = StrawberryAnnotation(other).resolve() + if isinstance(resolved, StrawberryType): + return self == resolved + else: + return NotImplemented + + def __hash__(self) -> int: + # TODO: Is this a bad idea? __eq__ objects are supposed to have the same hash + return id(self) + + +class StrawberryContainer(StrawberryType): + def __init__( + self, of_type: Union[StrawberryType, Type[WithStrawberryObjectDefinition], type] + ) -> None: + self.of_type = of_type + + def __hash__(self) -> int: + return hash((self.__class__, self.of_type)) + + def __eq__(self, other: object) -> bool: + if isinstance(other, StrawberryType): + if isinstance(other, StrawberryContainer): + return self.of_type == other.of_type + else: + return False + + return super().__eq__(other) + + @property + def type_params(self) -> List[TypeVar]: + if has_object_definition(self.of_type): + parameters = getattr(self.of_type, "__parameters__", None) + + return list(parameters) if parameters else [] + + elif isinstance(self.of_type, StrawberryType): + return self.of_type.type_params + + else: + return [] + + def copy_with( + self, + type_var_map: Mapping[ + str, Union[StrawberryType, Type[WithStrawberryObjectDefinition]] + ], + ) -> Self: + of_type_copy = self.of_type + + if has_object_definition(self.of_type): + type_definition = self.of_type.__strawberry_definition__ + + if type_definition.is_graphql_generic: + of_type_copy = type_definition.copy_with(type_var_map) + + elif ( + isinstance(self.of_type, StrawberryType) and self.of_type.is_graphql_generic + ): + of_type_copy = self.of_type.copy_with(type_var_map) + + return type(self)(of_type_copy) + + @property + def is_graphql_generic(self) -> bool: + from strawberry.schema.compat import is_graphql_generic + + type_ = self.of_type + + return is_graphql_generic(type_) + + def has_generic(self, type_var: TypeVar) -> bool: + if isinstance(self.of_type, StrawberryType): + return self.of_type.has_generic(type_var) + return False + + +class StrawberryList(StrawberryContainer): ... + + +class StrawberryOptional(StrawberryContainer): ... + + +class StrawberryTypeVar(StrawberryType): + def __init__(self, type_var: TypeVar) -> None: + self.type_var = type_var + + def copy_with( + self, type_var_map: Mapping[str, Union[StrawberryType, type]] + ) -> Union[StrawberryType, type]: + return type_var_map[self.type_var.__name__] + + @property + def is_graphql_generic(self) -> bool: + return True + + def has_generic(self, type_var: TypeVar) -> bool: + return self.type_var == type_var + + @property + def type_params(self) -> List[TypeVar]: + return [self.type_var] + + def __eq__(self, other: object) -> bool: + if isinstance(other, StrawberryTypeVar): + return self.type_var == other.type_var + if isinstance(other, TypeVar): + return self.type_var == other + + return super().__eq__(other) + + def __hash__(self) -> int: + return hash(self.type_var) + + +class WithStrawberryObjectDefinition(Protocol): + __strawberry_definition__: ClassVar[StrawberryObjectDefinition] + + +def has_object_definition( + obj: Any, +) -> TypeGuard[Type[WithStrawberryObjectDefinition]]: + if hasattr(obj, "__strawberry_definition__"): + return True + # TODO: Generics remove dunder members here, so we inject it here. + # Would be better to avoid it somehow. + # https://github.com/python/cpython/blob/3a314f7c3df0dd7c37da7d12b827f169ee60e1ea/Lib/typing.py#L1152 + if is_concrete_generic(obj): + concrete = obj.__origin__ + if hasattr(concrete, "__strawberry_definition__"): + obj.__strawberry_definition__ = concrete.__strawberry_definition__ + return True + return False + + +@overload +def get_object_definition( + obj: Any, + *, + strict: Literal[True], +) -> StrawberryObjectDefinition: ... + + +@overload +def get_object_definition( + obj: Any, + *, + strict: bool = False, +) -> Optional[StrawberryObjectDefinition]: ... + + +def get_object_definition( + obj: Any, + *, + strict: bool = False, +) -> Optional[StrawberryObjectDefinition]: + definition = obj.__strawberry_definition__ if has_object_definition(obj) else None + if strict and definition is None: + raise TypeError(f"{obj!r} does not have a StrawberryObjectDefinition") + + return definition @dataclasses.dataclass(eq=False) class StrawberryObjectDefinition(StrawberryType): - """ - Encapsulates definitions for Input / Object / interface GraphQL Types. + """Encapsulates definitions for Input / Object / interface GraphQL Types. In order get the definition from a decorated object you can use `has_object_definition` or `get_object_definition` as a shortcut. @@ -247,3 +457,17 @@ class TypeDefinition(StrawberryObjectDefinition): ... else: TypeDefinition = StrawberryObjectDefinition + + +__all__ = [ + "StrawberryContainer", + "StrawberryList", + "StrawberryObjectDefinition", + "StrawberryOptional", + "StrawberryType", + "StrawberryTypeVar", + "TypeDefinition", + "WithStrawberryObjectDefinition", + "get_object_definition", + "has_object_definition", +] diff --git a/strawberry/enum.py b/strawberry/types/enum.py similarity index 66% rename from strawberry/enum.py rename to strawberry/types/enum.py index 49bce07d24..4ec01be188 100644 --- a/strawberry/enum.py +++ b/strawberry/types/enum.py @@ -12,9 +12,8 @@ overload, ) -from strawberry.type import StrawberryType - -from .exceptions import ObjectIsNotAnEnumError +from strawberry.exceptions import ObjectIsNotAnEnumError +from strawberry.types.base import StrawberryType @dataclasses.dataclass @@ -67,6 +66,30 @@ def enum_value( directives: Iterable[object] = (), description: Optional[str] = None, ) -> EnumValueDefinition: + """Function to customise an enum value, for example to add a description or deprecation reason. + + Args: + value: The value of the enum member. + deprecation_reason: The deprecation reason of the enum member, + setting this will mark the enum member as deprecated. + directives: The directives to attach to the enum member. + description: The GraphQL description of the enum member. + + Returns: + An EnumValueDefinition object that can be used to customise an enum member. + + Example: + ```python + from enum import Enum + import strawberry + + + @strawberry.enum + class MyEnum(Enum): + FIRST_VALUE = strawberry.enum_value(description="The first value") + SECOND_VALUE = strawberry.enum_value(description="The second value") + ``` + """ return EnumValueDefinition( value=value, deprecation_reason=deprecation_reason, @@ -131,7 +154,7 @@ def _process_enum( @overload def enum( - _cls: EnumType, + cls: EnumType, *, name: Optional[str] = None, description: Optional[str] = None, @@ -141,7 +164,7 @@ def enum( @overload def enum( - _cls: None = None, + cls: None = None, *, name: Optional[str] = None, description: Optional[str] = None, @@ -150,13 +173,47 @@ def enum( def enum( - _cls: Optional[EnumType] = None, + cls: Optional[EnumType] = None, *, name: Optional[str] = None, description: Optional[str] = None, directives: Iterable[object] = (), ) -> Union[EnumType, Callable[[EnumType], EnumType]]: - """Registers the enum in the GraphQL type system. + """Annotates an Enum class a GraphQL enum. + + GraphQL enums only have names, while Python enums have names and values, + Strawberry will use the names of the Python enum as the names of the + GraphQL enum values. + + Args: + cls: The Enum class to be annotated. + name: The name of the GraphQL enum. + description: The description of the GraphQL enum. + directives: The directives to attach to the GraphQL enum. + + Returns: + The decorated Enum class. + + Example: + ```python + from enum import Enum + import strawberry + + + @strawberry.enum + class MyEnum(Enum): + FIRST_VALUE = "first_value" + SECOND_VALUE = "second_value" + ``` + + The above code will generate the following GraphQL schema: + + ```graphql + enum MyEnum { + FIRST_VALUE + SECOND_VALUE + } + ``` If name is passed, the name of the GraphQL type will be the value passed of name instead of the Enum class name. @@ -165,7 +222,10 @@ def enum( def wrap(cls: EnumType) -> EnumType: return _process_enum(cls, name, description, directives=directives) - if not _cls: + if not cls: return wrap - return wrap(_cls) + return wrap(cls) + + +__all__ = ["EnumValue", "EnumDefinition", "EnumValueDefinition", "enum", "enum_value"] diff --git a/strawberry/types/execution.py b/strawberry/types/execution.py index 9dc7ff7ef3..3cfda6556d 100644 --- a/strawberry/types/execution.py +++ b/strawberry/types/execution.py @@ -94,3 +94,6 @@ class ExecutionResult: class ParseOptions(TypedDict): max_tokens: NotRequired[int] + + +__all__ = ["ExecutionContext", "ExecutionResult", "ParseOptions"] diff --git a/strawberry/field.py b/strawberry/types/field.py similarity index 90% rename from strawberry/field.py rename to strawberry/types/field.py index 7af8b8c586..4c1fb8c812 100644 --- a/strawberry/field.py +++ b/strawberry/types/field.py @@ -24,25 +24,24 @@ from strawberry.annotation import StrawberryAnnotation from strawberry.exceptions import InvalidArgumentTypeError, InvalidDefaultFactoryError -from strawberry.type import ( +from strawberry.types.base import ( StrawberryType, WithStrawberryObjectDefinition, has_object_definition, ) -from strawberry.union import StrawberryUnion +from strawberry.types.union import StrawberryUnion -from .types.fields.resolver import StrawberryResolver +from .fields.resolver import StrawberryResolver if TYPE_CHECKING: import builtins from typing_extensions import Literal, Self - from strawberry.arguments import StrawberryArgument from strawberry.extensions.field_extension import FieldExtension + from strawberry.permission import BasePermission + from strawberry.types.arguments import StrawberryArgument + from strawberry.types.base import StrawberryObjectDefinition from strawberry.types.info import Info - from strawberry.types.types import StrawberryObjectDefinition - - from .permission import BasePermission T = TypeVar("T") @@ -64,7 +63,7 @@ def _is_generic(resolver_type: Union[StrawberryType, type]) -> bool: - """Returns True if `resolver_type` is generic else False""" + """Returns True if `resolver_type` is generic else False.""" if isinstance(resolver_type, StrawberryType): return resolver_type.is_graphql_generic @@ -149,7 +148,7 @@ def __init__( # Automatically add the permissions extension if len(self.permission_classes): - from .permission import PermissionExtension + from strawberry.permission import PermissionExtension if not self.extensions: self.extensions = [] @@ -189,8 +188,7 @@ def __copy__(self) -> Self: return new_field def __call__(self, resolver: _RESOLVER_TYPE) -> Self: - """Add a resolver to the field""" - + """Add a resolver to the field.""" # Allow for StrawberryResolvers or bare functions to be provided if not isinstance(resolver, StrawberryResolver): resolver = StrawberryResolver(resolver) @@ -217,12 +215,11 @@ def __call__(self, resolver: _RESOLVER_TYPE) -> Self: def get_result( self, source: Any, info: Optional[Info], args: List[Any], kwargs: Any ) -> Union[Awaitable[Any], Any]: - """ - Calls the resolver defined for the StrawberryField. + """Calls the resolver defined for the StrawberryField. + If the field doesn't have a resolver defined we default to using the default resolver specified in StrawberryConfig. """ - if self.base_resolver: return self.base_resolver(*args, **kwargs) @@ -230,8 +227,9 @@ def get_result( @property def is_basic_field(self) -> bool: - """ - Flag indicating if this is a "basic" field that has no resolver or + """Returns a boolean indicating if the field is a basic field. + + A "basic" field us a field that has no resolver or permission classes, i.e. it just returns the relevant attribute from the source object. If it is a basic field we can avoid constructing an `Info` object and running any permission checks in the resolver @@ -538,19 +536,44 @@ def field( ) -> Any: """Annotates a method or property as a GraphQL field. + Args: + resolver: The resolver for the field. This can be a function or a `StrawberryResolver`. + name: The GraphQL name of the field. + is_subscription: Whether the field is a subscription field. + description: The GraphQL description of the field. + permission_classes: The permission classes required to access the field. + deprecation_reason: The deprecation reason for the field. + default: The default value for the field. + default_factory: The default factory for the field. + metadata: The metadata for the field. + directives: The directives for the field. + extensions: The extensions for the field. + graphql_type: The GraphQL type for the field, useful when you want to use a + different type in the resolver than the one in the schema. + init: This parameter is used by PyRight to determine whether this field is + added in the constructor or not. It is not used to change any behavior + at the moment. + + Returns: + The field. + This is normally used inside a type declaration: - >>> @strawberry.type - >>> class X: - >>> field_abc: str = strawberry.field(description="ABC") + ```python + import strawberry + - >>> @strawberry.field(description="ABC") - >>> def field_with_resolver(self) -> str: - >>> return "abc" + @strawberry.type + class X: + field_abc: str = strawberry.field(description="ABC") + + @strawberry.field(description="ABC") + def field_with_resolver(self) -> str: + return "abc" + ``` it can be used both as decorator and as a normal function. """ - type_annotation = StrawberryAnnotation.from_annotation(graphql_type) field_ = StrawberryField( diff --git a/strawberry/types/fields/resolver.py b/strawberry/types/fields/resolver.py index 2aaf4d8472..ae0d1d98a7 100644 --- a/strawberry/types/fields/resolver.py +++ b/strawberry/types/fields/resolver.py @@ -23,13 +23,13 @@ from typing_extensions import Annotated, Protocol, get_origin from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument from strawberry.exceptions import ( ConflictingArgumentsError, MissingArgumentsAnnotationsError, ) from strawberry.parent import StrawberryParent -from strawberry.type import StrawberryType, has_object_definition +from strawberry.types.arguments import StrawberryArgument +from strawberry.types.base import StrawberryType, has_object_definition from strawberry.types.info import Info from strawberry.utils.typing import type_has_annotation diff --git a/strawberry/types/graphql.py b/strawberry/types/graphql.py index de58492e1e..92793bed3f 100644 --- a/strawberry/types/graphql.py +++ b/strawberry/types/graphql.py @@ -25,3 +25,6 @@ def from_http(method: HTTPMethod) -> Set[OperationType]: } raise ValueError(f"Unsupported HTTP method: {method}") # pragma: no cover + + +__all__ = ["OperationType"] diff --git a/strawberry/types/info.py b/strawberry/types/info.py index 879652508f..b5a95c924a 100644 --- a/strawberry/types/info.py +++ b/strawberry/types/info.py @@ -23,10 +23,13 @@ from graphql.language import FieldNode from graphql.pyutils.path import Path - from strawberry.arguments import StrawberryArgument - from strawberry.field import StrawberryField from strawberry.schema import Schema - from strawberry.type import StrawberryType, WithStrawberryObjectDefinition + from strawberry.types.arguments import StrawberryArgument + from strawberry.types.base import ( + StrawberryType, + WithStrawberryObjectDefinition, + ) + from strawberry.types.field import StrawberryField from .nodes import Selection @@ -36,6 +39,36 @@ @dataclasses.dataclass class Info(Generic[ContextType, RootValueType]): + """Class containing information about the current execution. + + This class is passed to resolvers when there's an argument with type `Info`. + + Example: + ```python + import strawberry + + + @strawberry.type + class Query: + @strawberry.field + def hello(self, info: strawberry.Info) -> str: + return f"Hello, {info.context['name']}!" + ``` + + It also supports passing the type of the context and root types: + + ```python + import strawberry + + + @strawberry.type + class Query: + @strawberry.field + def hello(self, info: strawberry.Info[str, str]) -> str: + return f"Hello, {info.context}!" + ``` + """ + _raw_info: GraphQLResolveInfo _field: StrawberryField @@ -48,7 +81,6 @@ def __class_getitem__(cls, types: Union[type, Tuple[type, ...]]) -> Type[Info]: See: https://discuss.python.org/t/passing-only-one-typevar-of-two-when-using-defaults/49134 """ - if not isinstance(types, tuple): types = (types, Any) # type: ignore @@ -56,10 +88,12 @@ def __class_getitem__(cls, types: Union[type, Tuple[type, ...]]) -> Type[Info]: @property def field_name(self) -> str: + """The name of the current field being resolved.""" return self._raw_info.field_name @property def schema(self) -> Schema: + """The schema of the current execution.""" return self._raw_info.schema._strawberry_schema # type: ignore @property @@ -74,48 +108,57 @@ def field_nodes(self) -> List[FieldNode]: # deprecated @cached_property def selected_fields(self) -> List[Selection]: + """The fields that were selected on the current field's type.""" info = self._raw_info return convert_selections(info, info.field_nodes) @property def context(self) -> ContextType: + """The context passed to the query execution.""" return self._raw_info.context @property def root_value(self) -> RootValueType: + """The root value passed to the query execution.""" return self._raw_info.root_value @property def variable_values(self) -> Dict[str, Any]: + """The variable values passed to the query execution.""" return self._raw_info.variable_values @property def return_type( self, ) -> Optional[Union[Type[WithStrawberryObjectDefinition], StrawberryType]]: + """The return type of the current field being resolved.""" return self._field.type @property def python_name(self) -> str: + """The name of the current field being resolved in Python format.""" return self._field.python_name # TODO: create an abstraction on these fields @property def operation(self) -> OperationDefinitionNode: + """The operation being executed.""" return self._raw_info.operation @property def path(self) -> Path: + """The path of the current field being resolved.""" return self._raw_info.path # TODO: parent_type as strawberry types # Helper functions def get_argument_definition(self, name: str) -> Optional[StrawberryArgument]: - """ - Get the StrawberryArgument definition for the current field by name. - """ + """Get the StrawberryArgument definition for the current field by name.""" try: return next(arg for arg in self._field.arguments if arg.python_name == name) except StopIteration: return None + + +__all__ = ["Info"] diff --git a/strawberry/lazy_type.py b/strawberry/types/lazy_type.py similarity index 70% rename from strawberry/lazy_type.py rename to strawberry/types/lazy_type.py index 278ff79a92..4ce2a30032 100644 --- a/strawberry/lazy_type.py +++ b/strawberry/types/lazy_type.py @@ -25,6 +25,14 @@ @dataclass(frozen=True) class LazyType(Generic[TypeName, Module]): + """A class that represents a type that will be resolved at runtime. + + This is useful when you have circular dependencies between types. + + This class is not meant to be used directly, instead use the `strawberry.lazy` + function. + """ + type_name: str module: str package: Optional[str] = None @@ -81,6 +89,14 @@ def __call__(self) -> None: # pragma: no cover class StrawberryLazyReference: + """A class that represents a lazy reference to a type in another module. + + This is useful when you have circular dependencies between types. + + This class is not meant to be used directly, instead use the `strawberry.lazy` + function. + """ + def __init__(self, module: str) -> None: self.module = module self.package = None @@ -105,4 +121,38 @@ def __hash__(self) -> int: def lazy(module_path: str) -> StrawberryLazyReference: + """Creates a lazy reference to a type in another module. + + Args: + module_path: The path to the module containing the type, supports relative paths + starting with `.` + + Returns: + A `StrawberryLazyReference` object that can be used to reference a type in another + module. + + This is useful when you have circular dependencies between types. + + For example, assuming you have a `Post` type that has a field `author` that + references a `User` type (which also has a field `posts` that references a list of + `Post`), you can use `strawberry.lazy` to avoid the circular dependency: + + ```python + from typing import TYPE_CHECKING, Annotated + + import strawberry + + if TYPE_CHECKING: + from .users import User + + + @strawberry.type + class Post: + title: str + author: Annotated["User", strawberry.lazy(".users")] + ``` + """ return StrawberryLazyReference(module_path) + + +__all__ = ["LazyType", "StrawberryLazyReference", "lazy"] diff --git a/strawberry/types/mutation.py b/strawberry/types/mutation.py new file mode 100644 index 0000000000..bf0bb2b792 --- /dev/null +++ b/strawberry/types/mutation.py @@ -0,0 +1,351 @@ +from __future__ import annotations + +import dataclasses +from typing import ( + TYPE_CHECKING, + Any, + Callable, + List, + Mapping, + Optional, + Sequence, + Type, + Union, + overload, +) +from typing_extensions import Literal + +from strawberry.types.field import ( + _RESOLVER_TYPE, + _RESOLVER_TYPE_ASYNC, + _RESOLVER_TYPE_SYNC, + StrawberryField, + T, + field, +) + +if TYPE_CHECKING: + from typing_extensions import Literal + + from strawberry.extensions.field_extension import FieldExtension + from strawberry.permission import BasePermission + +# NOTE: we are separating the sync and async resolvers because using both +# in the same function will cause mypy to raise an error. Not sure if it is a bug + + +@overload +def mutation( + *, + resolver: _RESOLVER_TYPE_ASYNC[T], + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[False] = False, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> T: ... + + +@overload +def mutation( + *, + resolver: _RESOLVER_TYPE_SYNC[T], + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[False] = False, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> T: ... + + +@overload +def mutation( + *, + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[True] = True, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> Any: ... + + +@overload +def mutation( + resolver: _RESOLVER_TYPE_ASYNC[T], + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> StrawberryField: ... + + +@overload +def mutation( + resolver: _RESOLVER_TYPE_SYNC[T], + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> StrawberryField: ... + + +def mutation( + resolver: Optional[_RESOLVER_TYPE[Any]] = None, + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, + # This init parameter is used by PyRight to determine whether this field + # is added in the constructor or not. It is not used to change + # any behavior at the moment. + init: Literal[True, False, None] = None, +) -> Any: + """Annotates a method or property as a GraphQL mutation. + + Args: + resolver: The resolver for the field. It can be a sync or async function. + name: The GraphQL name of the field. + description: The GraphQL description of the field. + permission_classes: The permission classes required to access the field. + deprecation_reason: The deprecation reason for the field. + default: The default value for the field. + default_factory: The default factory for the field. + metadata: The metadata for the field. + directives: The directives for the field. + extensions: The extensions for the field. + graphql_type: The GraphQL type for the field, useful when you want to use a + different type in the resolver than the one in the schema. + init: This parameter is used by PyRight to determine whether this field is + added in the constructor or not. It is not used to change any behavior at + the moment. + + Returns: + The field object. + + This is normally used inside a type declaration: + + ```python + import strawberry + + + @strawberry.type + class Mutation: + @strawberry.mutation + def create_post(self, title: str, content: str) -> Post: ... + ``` + + It can be used both as decorator and as a normal function. + """ + return field( + resolver=resolver, # type: ignore + name=name, + description=description, + permission_classes=permission_classes, + deprecation_reason=deprecation_reason, + default=default, + default_factory=default_factory, + metadata=metadata, + directives=directives, + extensions=extensions, + graphql_type=graphql_type, + ) + + +# NOTE: we are separating the sync and async resolvers because using both +# in the same function will cause mypy to raise an error. Not sure if it is a bug + + +@overload +def subscription( + *, + resolver: _RESOLVER_TYPE_ASYNC[T], + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[False] = False, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> T: ... + + +@overload +def subscription( + *, + resolver: _RESOLVER_TYPE_SYNC[T], + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[False] = False, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> T: ... + + +@overload +def subscription( + *, + name: Optional[str] = None, + description: Optional[str] = None, + init: Literal[True] = True, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> Any: ... + + +@overload +def subscription( + resolver: _RESOLVER_TYPE_ASYNC[T], + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> StrawberryField: ... + + +@overload +def subscription( + resolver: _RESOLVER_TYPE_SYNC[T], + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, +) -> StrawberryField: ... + + +def subscription( + resolver: Optional[_RESOLVER_TYPE[Any]] = None, + *, + name: Optional[str] = None, + description: Optional[str] = None, + permission_classes: Optional[List[Type[BasePermission]]] = None, + deprecation_reason: Optional[str] = None, + default: Any = dataclasses.MISSING, + default_factory: Union[Callable[..., object], object] = dataclasses.MISSING, + metadata: Optional[Mapping[Any, Any]] = None, + directives: Optional[Sequence[object]] = (), + extensions: Optional[List[FieldExtension]] = None, + graphql_type: Optional[Any] = None, + init: Literal[True, False, None] = None, +) -> Any: + """Annotates a method or property as a GraphQL subscription. + + Args: + resolver: The resolver for the field. + name: The GraphQL name of the field. + description: The GraphQL description of the field. + permission_classes: The permission classes required to access the field. + deprecation_reason: The deprecation reason for the field. + default: The default value for the field. + default_factory: The default factory for the field. + metadata: The metadata for the field. + directives: The directives for the field. + extensions: The extensions for the field. + graphql_type: The GraphQL type for the field, useful when you want to use a + different type in the resolver than the one in the schema. + init: This parameter is used by PyRight to determine whether this field is + added in the constructor or not. It is not used to change any behavior at + the moment. + + Returns: + The field for the subscription. + + This is normally used inside a type declaration: + + ```python + import strawberry + + + @strawberry.type + class Subscription: + @strawberry.subscription + def post_created(self, title: str, content: str) -> Post: ... + ``` + + it can be used both as decorator and as a normal function. + """ + return field( + resolver=resolver, # type: ignore + name=name, + description=description, + is_subscription=True, + permission_classes=permission_classes, + deprecation_reason=deprecation_reason, + default=default, + default_factory=default_factory, + metadata=metadata, + directives=directives, + extensions=extensions, + graphql_type=graphql_type, + ) + + +__all__ = ["mutation", "subscription"] diff --git a/strawberry/types/nodes.py b/strawberry/types/nodes.py index fc54c3f141..20a8407a8e 100644 --- a/strawberry/types/nodes.py +++ b/strawberry/types/nodes.py @@ -1,5 +1,4 @@ -""" -Abstraction layer for graphql-core field nodes. +"""Abstraction layer for graphql-core field nodes. Call `convert_sections` on a list of GraphQL `FieldNode`s, such as in `info.field_nodes`. @@ -151,3 +150,6 @@ def from_node(cls, info: GraphQLResolveInfo, node: GQLFieldNode) -> SelectedFiel info, getattr(node.selection_set, "selections", []) ), ) + + +__all__ = ["convert_selections", "FragmentSpread", "InlineFragment", "SelectedField"] diff --git a/strawberry/object_type.py b/strawberry/types/object_type.py similarity index 80% rename from strawberry/object_type.py rename to strawberry/types/object_type.py index 7c2b337419..5a9cea739e 100644 --- a/strawberry/object_type.py +++ b/strawberry/types/object_type.py @@ -16,20 +16,19 @@ ) from typing_extensions import dataclass_transform -from .exceptions import ( +from strawberry.exceptions import ( MissingFieldAnnotationError, MissingReturnAnnotationError, ObjectIsNotClassError, ) +from strawberry.types.base import get_object_definition +from strawberry.utils.dataclasses import add_custom_init_fn +from strawberry.utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor +from strawberry.utils.str_converters import to_camel_case + +from .base import StrawberryObjectDefinition from .field import StrawberryField, field -from .type import get_object_definition -from .types.type_resolver import _get_fields -from .types.types import ( - StrawberryObjectDefinition, -) -from .utils.dataclasses import add_custom_init_fn -from .utils.deprecations import DEPRECATION_MESSAGES, DeprecatedDescriptor -from .utils.str_converters import to_camel_case +from .type_resolver import _get_fields T = TypeVar("T", bound=Type) @@ -103,9 +102,7 @@ def _check_field_annotations(cls: Type[Any]) -> None: def _wrap_dataclass(cls: Type[T]) -> Type[T]: - """Wrap a strawberry.type class with a dataclass and check for any issues - before doing so""" - + """Wrap a strawberry.type class with a dataclass and check for any issues before doing so.""" # Ensure all Fields have been properly type-annotated _check_field_annotations(cls) @@ -232,11 +229,36 @@ def type( ) -> Union[T, Callable[[T], T]]: """Annotates a class as a GraphQL type. + Similar to `dataclasses.dataclass`, but with additional functionality for + defining GraphQL types. + + Args: + cls: The class we want to create a GraphQL type from. + name: The name of the GraphQL type. + is_input: Whether the class is an input type. Used internally, use `@strawerry.input` instead of passing this flag. + is_interface: Whether the class is an interface. Used internally, use `@strawerry.interface` instead of passing this flag. + description: The description of the GraphQL type. + directives: The directives of the GraphQL type. + extend: Whether the class is extending an existing type. + + Returns: + The class. + Example usage: - >>> @strawberry.type - >>> class X: - >>> field_abc: str = "ABC" + ```python + @strawberry.type + class User: + name: str = "A name" + ``` + + You can also pass parameters to the decorator: + + ```python + @strawberry.type(name="UserType", description="A user type") + class MyUser: + name: str = "A name" + ``` """ def wrap(cls: T) -> T: @@ -321,12 +343,35 @@ def input( directives: Optional[Sequence[object]] = (), ): """Annotates a class as a GraphQL Input type. + + Similar to `@strawberry.type`, but for input types. + + Args: + cls: The class we want to create a GraphQL input type from. + name: The name of the GraphQL input type. + description: The description of the GraphQL input type. + directives: The directives of the GraphQL input type. + one_of: Whether the input type is a `oneOf` type. + + Returns: + The class. + Example usage: - >>> @strawberry.input - >>> class X: - >>> field_abc: str = "ABC" - """ + ```python + @strawberry.input + class UserInput: + name: str + ``` + + You can also pass parameters to the decorator: + + ```python + @strawberry.input(name="UserInputType", description="A user input type") + class MyUserInput: + name: str + ``` + """ from strawberry.schema_directives import OneOf if one_of: @@ -377,12 +422,34 @@ def interface( directives: Optional[Sequence[object]] = (), ): """Annotates a class as a GraphQL Interface. + + Similar to `@strawberry.type`, but for interfaces. + + Args: + cls: The class we want to create a GraphQL interface from. + name: The name of the GraphQL interface. + description: The description of the GraphQL interface. + directives: The directives of the GraphQL interface. + + Returns: + The class. + Example usage: - >>> @strawberry.interface - >>> class X: - >>> field_abc: str - """ + ```python + @strawberry.interface + class Node: + id: str + ``` + + You can also pass parameters to the decorator: + + ```python + @strawberry.interface(name="NodeType", description="A node type") + class MyNode: + id: str + ``` + """ return type( # type: ignore # not sure why mypy complains here cls, name=name, @@ -394,15 +461,27 @@ def interface( def asdict(obj: Any) -> Dict[str, object]: """Convert a strawberry object into a dictionary. + This wraps the dataclasses.asdict function to strawberry. + Args: + obj: The object to convert into a dictionary. + + Returns: + A dictionary representation of the object. + Example usage: - >>> @strawberry.type - >>> class User: - >>> name: str - >>> age: int - >>> # should be {"name": "Lorem", "age": 25} - >>> user_dict = strawberry.asdict(User(name="Lorem", age=25)) + + ```python + @strawberry.type + class User: + name: str + age: int + + + strawberry.asdict(User(name="Lorem", age=25)) + # {"name": "Lorem", "age": 25} + ``` """ return dataclasses.asdict(obj) diff --git a/strawberry/private.py b/strawberry/types/private.py similarity index 60% rename from strawberry/private.py rename to strawberry/types/private.py index 65d03a3ffe..cd35d6ac0d 100644 --- a/strawberry/private.py +++ b/strawberry/types/private.py @@ -10,17 +10,24 @@ class StrawberryPrivate: ... T = TypeVar("T") Private = Annotated[T, StrawberryPrivate()] -Private.__doc__ = """Represents a field that won't be exposed in the GraphQL schema +"""Represents a field that won't be exposed in the GraphQL schema. Example: ->>> import strawberry ->>> @strawberry.type -... class User: -... name: str -... age: strawberry.Private[int] +```python +import strawberry + + +@strawberry.type +class User: + name: str + age: strawberry.Private[int] +``` """ def is_private(type_: object) -> bool: return type_has_annotation(type_, StrawberryPrivate) + + +__all__ = ["Private", "is_private"] diff --git a/strawberry/custom_scalar.py b/strawberry/types/scalar.py similarity index 80% rename from strawberry/custom_scalar.py rename to strawberry/types/scalar.py index 104020196b..c5adf22ae8 100644 --- a/strawberry/custom_scalar.py +++ b/strawberry/types/scalar.py @@ -16,9 +16,8 @@ ) from strawberry.exceptions import InvalidUnionTypeError -from strawberry.type import StrawberryType - -from .utils.str_converters import to_camel_case +from strawberry.types.base import StrawberryType +from strawberry.utils.str_converters import to_camel_case if TYPE_CHECKING: from graphql import GraphQLScalarType @@ -166,30 +165,44 @@ def scalar( ) -> Any: """Annotates a class or type as a GraphQL custom scalar. + Args: + cls: The class or type to annotate. + name: The GraphQL name of the scalar. + description: The description of the scalar. + specified_by_url: The URL of the specification. + serialize: The function to serialize the scalar. + parse_value: The function to parse the value. + parse_literal: The function to parse the literal. + directives: The directives to apply to the scalar. + + Returns: + The decorated class or type. + Example usages: - >>> strawberry.scalar( - >>> datetime.date, - >>> serialize=lambda value: value.isoformat(), - >>> parse_value=datetime.parse_date - >>> ) - - >>> Base64Encoded = strawberry.scalar( - >>> NewType("Base64Encoded", bytes), - >>> serialize=base64.b64encode, - >>> parse_value=base64.b64decode - >>> ) - - >>> @strawberry.scalar( - >>> serialize=lambda value: ",".join(value.items), - >>> parse_value=lambda value: CustomList(value.split(",")) - >>> ) - >>> class CustomList: - >>> def __init__(self, items): - >>> self.items = items + ```python + strawberry.scalar( + datetime.date, + serialize=lambda value: value.isoformat(), + parse_value=datetime.parse_date, + ) - """ + Base64Encoded = strawberry.scalar( + NewType("Base64Encoded", bytes), + serialize=base64.b64encode, + parse_value=base64.b64decode, + ) + + @strawberry.scalar( + serialize=lambda value: ",".join(value.items), + parse_value=lambda value: CustomList(value.split(",")), + ) + class CustomList: + def __init__(self, items): + self.items = items + ``` + """ if parse_value is None: parse_value = cls @@ -209,3 +222,6 @@ def wrap(cls: _T) -> ScalarWrapper: return wrap return wrap(cls) + + +__all__ = ["ScalarDefinition", "ScalarWrapper", "scalar"] diff --git a/strawberry/types/type_resolver.py b/strawberry/types/type_resolver.py index 2db7a4b638..975980880e 100644 --- a/strawberry/types/type_resolver.py +++ b/strawberry/types/type_resolver.py @@ -10,16 +10,16 @@ FieldWithResolverAndDefaultValueError, PrivateStrawberryFieldError, ) -from strawberry.field import StrawberryField -from strawberry.private import is_private -from strawberry.type import has_object_definition -from strawberry.unset import UNSET +from strawberry.types.base import has_object_definition +from strawberry.types.field import StrawberryField +from strawberry.types.private import is_private +from strawberry.types.unset import UNSET def _get_fields( cls: Type[Any], original_type_annotations: Dict[str, Type[Any]] ) -> List[StrawberryField]: - """Get all the strawberry fields off a strawberry.type cls + """Get all the strawberry fields off a strawberry.type cls. This function returns a list of StrawberryFields (one for each field item), while also paying attention the name and typing of the field. @@ -27,16 +27,19 @@ def _get_fields( StrawberryFields can be defined on a strawberry.type class as either a dataclass- style field or using strawberry.field as a decorator. - >>> import strawberry - >>> @strawberry.type - ... class Query: - ... type_1a: int = 5 - ... type_1b: int = strawberry.field(...) - ... type_1c: int = strawberry.field(resolver=...) - ... - ... @strawberry.field - ... def type_2(self) -> int: - ... ... + ```python + import strawberry + + + @strawberry.type + class Query: + type_1a: int = 5 + type_1b: int = strawberry.field(...) + type_1c: int = strawberry.field(resolver=...) + + @strawberry.field + def type_2(self) -> int: ... + ``` Type #1: A pure dataclass-style field. Will not have a StrawberryField; one will need to @@ -51,7 +54,6 @@ class if one is not set by either using an explicit strawberry.field(name=...) o passing a named function (i.e. not an anonymous lambda) to strawberry.field (typically as a decorator). """ - fields: Dict[str, StrawberryField] = {} # before trying to find any fields, let's first add the fields defined in @@ -163,3 +165,6 @@ class if one is not set by either using an explicit strawberry.field(name=...) o fields[field_name] = field return list(fields.values()) + + +__all__ = ["_get_fields"] diff --git a/strawberry/union.py b/strawberry/types/union.py similarity index 92% rename from strawberry/union.py rename to strawberry/types/union.py index f0a319a5a9..f1e32fba68 100644 --- a/strawberry/union.py +++ b/strawberry/types/union.py @@ -31,12 +31,12 @@ WrongReturnTypeForUnion, ) from strawberry.exceptions.handler import should_use_rich_exceptions -from strawberry.lazy_type import LazyType -from strawberry.type import ( +from strawberry.types.base import ( StrawberryOptional, StrawberryType, has_object_definition, ) +from strawberry.types.lazy_type import LazyType if TYPE_CHECKING: from graphql import ( @@ -173,7 +173,7 @@ def _resolve_union_type( ) -> str: assert isinstance(type_, GraphQLUnionType) - from strawberry.types.types import StrawberryObjectDefinition + from strawberry.types.base import StrawberryObjectDefinition # If the type given is not an Object type, try resolving using `is_type_of` # defined on the union's inner types @@ -250,15 +250,27 @@ def union( ) -> StrawberryUnion: """Creates a new named Union type. + Args: + name: The GraphQL name of the Union type. + types: The types that the Union can be. + (Deprecated, use `Annotated[U, strawberry.union("Name")]` instead) + description: The GraphQL description of the Union type. + directives: The directives to attach to the Union type. + Example usages: - >>> @strawberry.type - ... class A: ... - >>> @strawberry.type - ... class B: ... - >>> Annotated[A | B, strawberry.union("Name")] - """ + ```python + import strawberry + from typing import Annotated + + @strawberry.type + class A: ... + + @strawberry.type + class B: ... + MyUnion = Annotated[A | B, strawberry.union("Name")] + """ if types is None: union = StrawberryUnion( name=name, @@ -299,3 +311,6 @@ def union( description=description, directives=directives, ) + + +__all__ = ["StrawberryUnion", "union"] diff --git a/strawberry/unset.py b/strawberry/types/unset.py similarity index 64% rename from strawberry/unset.py rename to strawberry/types/unset.py index 6a3444ce30..31c8012b73 100644 --- a/strawberry/unset.py +++ b/strawberry/types/unset.py @@ -28,6 +28,26 @@ def __bool__(self) -> bool: UNSET: Any = UnsetType() +"""A special value that can be used to represent an unset value in a field or argument. +Similar to `undefined` in JavaScript, this value can be used to differentiate between +a field that was not set and a field that was set to `None` or `null`. + +Example: + +```python +import strawberry + + +@strawberry.input +class UserInput: + name: str | None = strawberry.UNSET + age: int | None = strawberry.UNSET +``` + +In the example above, if `name` or `age` are not provided when creating a `UserInput` +object, they will be set to `UNSET` instead of `None`. Use `is UNSET` to check +whether a value is unset. +""" def _deprecated_is_unset(value: Any) -> bool: diff --git a/strawberry/utils/aio.py b/strawberry/utils/aio.py index a20ec97ed1..7ffd8f9e67 100644 --- a/strawberry/utils/aio.py +++ b/strawberry/utils/aio.py @@ -67,3 +67,11 @@ async def resolve_awaitable( ) -> _R: """Resolves an awaitable object and calls a callback with the resolved value.""" return callback(await awaitable) + + +__all__ = [ + "aenumerate", + "aislice", + "asyncgen_to_list", + "resolve_awaitable", +] diff --git a/strawberry/utils/await_maybe.py b/strawberry/utils/await_maybe.py index ee79716082..ecdfe5449c 100644 --- a/strawberry/utils/await_maybe.py +++ b/strawberry/utils/await_maybe.py @@ -12,3 +12,6 @@ async def await_maybe(value: AwaitableOrValue[T]) -> T: return await value return cast(T, value) + + +__all__ = ["await_maybe", "AwaitableOrValue", "AsyncIteratorOrIterator"] diff --git a/strawberry/utils/dataclasses.py b/strawberry/utils/dataclasses.py index 62e835f6e8..eadd0ed1be 100644 --- a/strawberry/utils/dataclasses.py +++ b/strawberry/utils/dataclasses.py @@ -32,3 +32,6 @@ def add_custom_init_fn(cls: Any) -> None: globals_=globals_, ), ) + + +__all__ = ["add_custom_init_fn"] diff --git a/strawberry/utils/debug.py b/strawberry/utils/debug.py index 1a59086fb3..825a2ccc24 100644 --- a/strawberry/utils/debug.py +++ b/strawberry/utils/debug.py @@ -14,8 +14,8 @@ def pretty_print_graphql_operation( ) -> None: """Pretty print a GraphQL operation using pygments. - Won't print introspection operation to prevent noise in the output.""" - + Won't print introspection operation to prevent noise in the output. + """ try: from pygments import highlight, lexers from pygments.formatters import Terminal256Formatter @@ -41,3 +41,6 @@ def pretty_print_graphql_operation( print( # noqa: T201 highlight(variables_json, lexers.JsonLexer(), Terminal256Formatter()) ) + + +__all__ = ["pretty_print_graphql_operation"] diff --git a/strawberry/utils/deprecations.py b/strawberry/utils/deprecations.py index aa722c92d6..4e802c5b43 100644 --- a/strawberry/utils/deprecations.py +++ b/strawberry/utils/deprecations.py @@ -25,3 +25,6 @@ def __get__(self, obj: Optional[object], type: Optional[Type] = None) -> Any: def inject(self, klass: type) -> None: setattr(klass, self.attr_name, self) + + +__all__ = ["DEPRECATION_MESSAGES", "DeprecatedDescriptor"] diff --git a/strawberry/utils/graphql_lexer.py b/strawberry/utils/graphql_lexer.py index ffe02937c6..4e23668dd7 100644 --- a/strawberry/utils/graphql_lexer.py +++ b/strawberry/utils/graphql_lexer.py @@ -28,3 +28,6 @@ class GraphQLLexer(RegexLexer): (r"(\s|,)", token.Text), ] } + + +__all__ = ["GraphQLLexer"] diff --git a/strawberry/utils/importer.py b/strawberry/utils/importer.py index 90dc81f02d..7179245c61 100644 --- a/strawberry/utils/importer.py +++ b/strawberry/utils/importer.py @@ -19,3 +19,6 @@ def import_module_symbol( symbol = getattr(symbol, attribute_name) return symbol + + +__all__ = ["import_module_symbol"] diff --git a/strawberry/utils/inspect.py b/strawberry/utils/inspect.py index 5a543b42fa..4ed67c6be4 100644 --- a/strawberry/utils/inspect.py +++ b/strawberry/utils/inspect.py @@ -12,7 +12,6 @@ ) from typing_extensions import get_args -from strawberry.type import has_object_definition from strawberry.utils.typing import is_generic_alias @@ -29,8 +28,7 @@ def in_async_context() -> bool: @lru_cache(maxsize=250) def get_func_args(func: Callable[[Any], Any]) -> List[str]: - """Returns a list of arguments for the function""" - + """Returns a list of arguments for the function.""" sig = inspect.signature(func) return [ @@ -45,38 +43,46 @@ def get_specialized_type_var_map(cls: type) -> Optional[Dict[str, type]]: Consider the following: - >>> class Foo(Generic[T]): - ... ... - ... - >>> class Bar(Generic[K]): - ... ... - ... - >>> class IntBar(Bar[int]): - ... ... - ... - >>> class IntBarSubclass(IntBar): - ... ... - ... - >>> class IntBarFoo(IntBar, Foo[str]): - ... ... - ... + ```python + class Foo(Generic[T]): ... + + + class Bar(Generic[K]): ... + + + class IntBar(Bar[int]): ... + + + class IntBarSubclass(IntBar): ... + + + class IntBarFoo(IntBar, Foo[str]): ... + ``` This would return: - >>> get_specialized_type_var_map(object) - None - >>> get_specialized_type_var_map(Foo) - {} - >>> get_specialized_type_var_map(Bar) - {~T: ~T} - >>> get_specialized_type_var_map(IntBar) - {~T: int} - >>> get_specialized_type_var_map(IntBarSubclass) - {~T: int} - >>> get_specialized_type_var_map(IntBarFoo) - {~T: int, ~K: str} + ```python + get_specialized_type_var_map(object) + # None + + get_specialized_type_var_map(Foo) + # {} + + get_specialized_type_var_map(Bar) + # {~T: ~T} + + get_specialized_type_var_map(IntBar) + # {~T: int} + get_specialized_type_var_map(IntBarSubclass) + # {~T: int} + + get_specialized_type_var_map(IntBarFoo) + # {~T: int, ~K: str} + ``` """ + from strawberry.types.base import has_object_definition + orig_bases = getattr(cls, "__orig_bases__", None) if orig_bases is None: # Specialized generic aliases will not have __orig_bases__ @@ -114,3 +120,6 @@ def get_specialized_type_var_map(cls: type) -> Optional[Dict[str, type]]: ) return type_var_map + + +__all__ = ["in_async_context", "get_func_args", "get_specialized_type_var_map"] diff --git a/strawberry/utils/logging.py b/strawberry/utils/logging.py index d19fd49bce..0a701a7701 100644 --- a/strawberry/utils/logging.py +++ b/strawberry/utils/logging.py @@ -23,3 +23,6 @@ def error( **logger_kwargs: Any, ) -> None: cls.logger.error(error, exc_info=error.original_error, **logger_kwargs) + + +__all__ = ["StrawberryLogger"] diff --git a/strawberry/utils/operation.py b/strawberry/utils/operation.py index dcca27a907..78eb95119e 100644 --- a/strawberry/utils/operation.py +++ b/strawberry/utils/operation.py @@ -38,3 +38,6 @@ def get_operation_type( raise RuntimeError("Can't get GraphQL operation type") return OperationType(definition.operation.value) + + +__all__ = ["get_first_operation", "get_operation_type"] diff --git a/strawberry/utils/str_converters.py b/strawberry/utils/str_converters.py index 7bad6fc751..9c52a7ed7d 100644 --- a/strawberry/utils/str_converters.py +++ b/strawberry/utils/str_converters.py @@ -24,3 +24,6 @@ def capitalize_first(name: str) -> str: def to_snake_case(name: str) -> str: name = re.sub("(.)([A-Z][a-z]+)", r"\1_\2", name) return re.sub("([a-z0-9])([A-Z])", r"\1_\2", name).lower() + + +__all__ = ["to_camel_case", "to_kebab_case", "capitalize_first", "to_snake_case"] diff --git a/strawberry/utils/typing.py b/strawberry/utils/typing.py index 83ef1eff68..e88d3edd92 100644 --- a/strawberry/utils/typing.py +++ b/strawberry/utils/typing.py @@ -44,10 +44,13 @@ def get_generic_alias(type_: Type) -> Type: Given a type, its generic alias from `typing` module will be returned if it exists. For example: - >>> get_generic_alias(list) - typing.List - >>> get_generic_alias(dict) - typing.Dict + ```python + get_generic_alias(list) + # typing.List + + get_generic_alias(dict) + # typing.Dict + ``` This is mostly useful for python versions prior to 3.9, to get a version of a concrete type which supports `__class_getitem__`. In 3.9+ types like @@ -78,16 +81,14 @@ def is_generic_alias(type_: Any) -> TypeGuard[_GenericAlias]: def is_list(annotation: object) -> bool: - """Returns True if annotation is a List""" - + """Returns True if annotation is a List.""" annotation_origin = getattr(annotation, "__origin__", None) return annotation_origin == list def is_union(annotation: object) -> bool: - """Returns True if annotation is a Union""" - + """Returns True if annotation is a Union.""" # this check is needed because unions declared with the new syntax `A | B` # don't have a `__origin__` property on them, but they are instances of # `UnionType`, which is only available in Python 3.10+ @@ -105,8 +106,7 @@ def is_union(annotation: object) -> bool: def is_optional(annotation: Type) -> bool: - """Returns True if the annotation is Optional[SomeType]""" - + """Returns True if the annotation is Optional[SomeType].""" # Optionals are represented as unions if not is_union(annotation): @@ -153,7 +153,6 @@ def is_generic_subclass(annotation: type) -> bool: def is_generic(annotation: type) -> bool: """Returns True if the annotation is or extends a generic.""" - return ( # TODO: These two lines appear to have the same effect. When will an # annotation have parameters but not satisfy the first condition? @@ -164,7 +163,6 @@ def is_generic(annotation: type) -> bool: def is_type_var(annotation: Type) -> bool: """Returns True if the annotation is a TypeVar.""" - return isinstance(annotation, TypeVar) @@ -259,7 +257,7 @@ def _get_namespace_from_ast( globalns: Optional[Dict] = None, localns: Optional[Dict] = None, ) -> Dict[str, Type]: - from strawberry.lazy_type import StrawberryLazyReference + from strawberry.types.lazy_type import StrawberryLazyReference extra = {} @@ -328,9 +326,9 @@ def eval_type( localns: Optional[Dict] = None, ) -> Type: """Evaluates a type, resolving forward references.""" - from strawberry.auto import StrawberryAuto - from strawberry.lazy_type import StrawberryLazyReference - from strawberry.private import StrawberryPrivate + from strawberry.types.auto import StrawberryAuto + from strawberry.types.lazy_type import StrawberryLazyReference + from strawberry.types.private import StrawberryPrivate globalns = globalns or {} # If this is not a string, maybe its args are (e.g. List["Foo"]) @@ -411,3 +409,22 @@ def eval_type( ) return type_ + + +__all__ = [ + "get_generic_alias", + "is_generic_alias", + "is_list", + "is_union", + "is_optional", + "get_optional_annotation", + "get_list_annotation", + "is_concrete_generic", + "is_generic_subclass", + "is_generic", + "is_type_var", + "is_classvar", + "type_has_annotation", + "get_parameters", + "eval_type", +] diff --git a/tests/codemods/test_imports.py b/tests/codemods/test_imports.py new file mode 100644 index 0000000000..896fe325e8 --- /dev/null +++ b/tests/codemods/test_imports.py @@ -0,0 +1,176 @@ +from libcst.codemod import CodemodTest + +from strawberry.codemods.update_imports import UpdateImportsCodemod + + +class TestConvertConstantCommand(CodemodTest): + TRANSFORM = UpdateImportsCodemod + + def test_update_field(self) -> None: + before = """ + from strawberry.field import something + """ + + after = """ + from strawberry.types.field import something + """ + + self.assertCodemod(before, after) + + def test_update_import_strawberry_type(self) -> None: + before = """ + from strawberry.type import ( + StrawberryContainer, + StrawberryList, + StrawberryOptional, + StrawberryType, + WithStrawberryObjectDefinition, + ) + """ + + after = """ + from strawberry.types.base import ( + StrawberryContainer, + StrawberryList, + StrawberryOptional, + StrawberryType, + WithStrawberryObjectDefinition, + ) + """ + + self.assertCodemod(before, after) + + def test_update_import_strawberry_type_object_definition(self) -> None: + before = """ + from strawberry.type import ( + StrawberryContainer, + StrawberryList, + StrawberryOptional, + StrawberryType, + WithStrawberryObjectDefinition, + get_object_definition, + has_object_definition, + ) + """ + + after = """ + from strawberry.types.base import ( + StrawberryContainer, + StrawberryList, + StrawberryOptional, + StrawberryType, + WithStrawberryObjectDefinition) + from strawberry.types import get_object_definition, has_object_definition + """ + + self.assertCodemod(before, after) + + def test_update_import_strawberry_type_object_definition_only(self) -> None: + before = """ + from strawberry.type import get_object_definition + """ + + after = """ + from strawberry.types import get_object_definition + """ + + self.assertCodemod(before, after) + + def test_update_import_union(self) -> None: + before = """ + from strawberry.union import StrawberryUnion + """ + + after = """ + from strawberry.types.union import StrawberryUnion + """ + + self.assertCodemod(before, after) + + def test_update_import_auto(self) -> None: + before = """ + from strawberry.auto import auto + """ + + after = """ + from strawberry.types.auto import auto + """ + + self.assertCodemod(before, after) + + def test_update_import_unset(self) -> None: + before = """ + from strawberry.unset import UNSET + """ + + after = """ + from strawberry.types.unset import UNSET + """ + + self.assertCodemod(before, after) + + def test_update_import_arguments(self) -> None: + before = """ + from strawberry.arguments import StrawberryArgument + """ + + after = """ + from strawberry.types.arguments import StrawberryArgument + """ + + self.assertCodemod(before, after) + + def test_update_import_lazy_type(self) -> None: + before = """ + from strawberry.lazy_type import LazyType + """ + + after = """ + from strawberry.types.lazy_type import LazyType + """ + + self.assertCodemod(before, after) + + def test_update_import_object_type(self) -> None: + before = """ + from strawberry.object_type import StrawberryObjectDefinition + """ + + after = """ + from strawberry.types.object_type import StrawberryObjectDefinition + """ + + self.assertCodemod(before, after) + + def test_update_import_enum(self) -> None: + before = """ + from strawberry.enum import StrawberryEnum + """ + + after = """ + from strawberry.types.enum import StrawberryEnum + """ + + self.assertCodemod(before, after) + + def test_update_types_types(self) -> None: + before = """ + from strawberry.types.types import StrawberryObjectDefinition + """ + + after = """ + from strawberry.types.base import StrawberryObjectDefinition + """ + + self.assertCodemod(before, after) + + def test_update_is_private(self) -> None: + before = """ + from strawberry.private import is_private + """ + + after = """ + from strawberry.types.private import is_private + """ + + self.assertCodemod(before, after) diff --git a/tests/enums/test_enum.py b/tests/enums/test_enum.py index 827e282909..2189fba3d6 100644 --- a/tests/enums/test_enum.py +++ b/tests/enums/test_enum.py @@ -3,9 +3,9 @@ import pytest import strawberry -from strawberry.enum import EnumDefinition from strawberry.exceptions import ObjectIsNotAnEnumError from strawberry.exceptions.not_a_strawberry_enum import NotAStrawberryEnumError +from strawberry.types.enum import EnumDefinition def test_basic_enum(): diff --git a/tests/experimental/pydantic/test_basic.py b/tests/experimental/pydantic/test_basic.py index 1b70b6d53e..9556d3f617 100644 --- a/tests/experimental/pydantic/test_basic.py +++ b/tests/experimental/pydantic/test_basic.py @@ -7,12 +7,15 @@ import pytest import strawberry -from strawberry.enum import EnumDefinition from strawberry.experimental.pydantic.exceptions import MissingFieldsListError from strawberry.schema_directive import Location -from strawberry.type import StrawberryList, StrawberryOptional -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion +from strawberry.types.base import ( + StrawberryList, + StrawberryObjectDefinition, + StrawberryOptional, +) +from strawberry.types.enum import EnumDefinition +from strawberry.types.union import StrawberryUnion def test_basic_type_field_list(): diff --git a/tests/experimental/pydantic/test_conversion.py b/tests/experimental/pydantic/test_conversion.py index 5fcfdcc635..cc9b5a81e0 100644 --- a/tests/experimental/pydantic/test_conversion.py +++ b/tests/experimental/pydantic/test_conversion.py @@ -19,8 +19,11 @@ BothDefaultAndDefaultFactoryDefinedError, ) from strawberry.experimental.pydantic.utils import get_default_factory_for_field -from strawberry.type import StrawberryList, StrawberryOptional -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import ( + StrawberryList, + StrawberryObjectDefinition, + StrawberryOptional, +) from tests.experimental.pydantic.utils import needs_pydantic_v1 diff --git a/tests/experimental/pydantic/test_error_type.py b/tests/experimental/pydantic/test_error_type.py index 969c61b87a..8e37c6402c 100644 --- a/tests/experimental/pydantic/test_error_type.py +++ b/tests/experimental/pydantic/test_error_type.py @@ -5,8 +5,11 @@ import strawberry from strawberry.experimental.pydantic.exceptions import MissingFieldsListError -from strawberry.type import StrawberryList, StrawberryOptional -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import ( + StrawberryList, + StrawberryObjectDefinition, + StrawberryOptional, +) def test_basic_error_type_fields(): diff --git a/tests/experimental/pydantic/test_fields.py b/tests/experimental/pydantic/test_fields.py index b26b8e104e..878969b9af 100644 --- a/tests/experimental/pydantic/test_fields.py +++ b/tests/experimental/pydantic/test_fields.py @@ -8,8 +8,7 @@ import strawberry from strawberry.experimental.pydantic._compat import IS_PYDANTIC_V1 -from strawberry.type import StrawberryOptional -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import StrawberryObjectDefinition, StrawberryOptional from tests.experimental.pydantic.utils import needs_pydantic_v1, needs_pydantic_v2 diff --git a/tests/fields/test_arguments.py b/tests/fields/test_arguments.py index c9ae8508b9..90cc15d2ed 100644 --- a/tests/fields/test_arguments.py +++ b/tests/fields/test_arguments.py @@ -11,7 +11,7 @@ InvalidArgumentTypeError, MultipleStrawberryArgumentsError, ) -from strawberry.type import StrawberryList, StrawberryOptional +from strawberry.types.base import StrawberryList, StrawberryOptional def test_basic_arguments(): @@ -482,14 +482,14 @@ class Mutation: def test_unset_deprecation_warning(): with pytest.deprecated_call(): - from strawberry.arguments import UNSET # noqa: F401 + from strawberry.types.arguments import UNSET # noqa: F401 with pytest.deprecated_call(): - from strawberry.arguments import is_unset # noqa: F401 + from strawberry.types.arguments import is_unset # noqa: F401 def test_deprecated_unset(): with pytest.deprecated_call(): - from strawberry.unset import is_unset + from strawberry.types.unset import is_unset with warnings.catch_warnings(record=False): assert is_unset(UNSET) diff --git a/tests/fields/test_field_defaults.py b/tests/fields/test_field_defaults.py index a84928fc19..2ca92069c5 100644 --- a/tests/fields/test_field_defaults.py +++ b/tests/fields/test_field_defaults.py @@ -8,7 +8,7 @@ FieldWithResolverAndDefaultValueError, InvalidDefaultFactoryError, ) -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField def test_field_with_default(): diff --git a/tests/fields/test_field_exceptions.py b/tests/fields/test_field_exceptions.py index 11635ff92a..7eeeb3f60b 100644 --- a/tests/fields/test_field_exceptions.py +++ b/tests/fields/test_field_exceptions.py @@ -10,7 +10,7 @@ FieldWithResolverAndDefaultValueError, ) from strawberry.extensions.field_extension import FieldExtension -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField def test_field_with_resolver_default(): diff --git a/tests/fields/test_resolvers.py b/tests/fields/test_resolvers.py index 74d4ceb222..3f6be393a6 100644 --- a/tests/fields/test_resolvers.py +++ b/tests/fields/test_resolvers.py @@ -222,7 +222,8 @@ class Query: def test_raises_error_when_missing_type(): """Test to make sure that if somehow a non-StrawberryField field is added to the cls without annotations it raises an exception. This would occur if someone manually - uses dataclasses.field""" + uses dataclasses.field + """ @strawberry.type class Query: diff --git a/tests/http/clients/base.py b/tests/http/clients/base.py index 132f641a60..8ccbaa1d62 100644 --- a/tests/http/clients/base.py +++ b/tests/http/clients/base.py @@ -173,9 +173,7 @@ def _build_multipart_file_map( return files_map def create_app(self, **kwargs: Any) -> None: - """ - For use by websocket tests - """ + """For use by websocket tests.""" raise NotImplementedError async def ws_connect( @@ -234,9 +232,8 @@ async def __aiter__(self) -> AsyncGenerator[Message, None]: class DebuggableGraphQLTransportWSMixin: @staticmethod def on_init(self) -> None: - """ - This method can be patched by unittests to get the instance of the - transport handler when it is initialized + """This method can be patched by unittests to get the instance of the + transport handler when it is initialized. """ def __init__(self, *args: Any, **kwargs: Any): diff --git a/tests/http/clients/channels.py b/tests/http/clients/channels.py index ee31c8e88b..da981403bb 100644 --- a/tests/http/clients/channels.py +++ b/tests/http/clients/channels.py @@ -131,9 +131,7 @@ def process_result( class ChannelsHttpClient(HttpClient): - """ - A client to test websockets over channels - """ + """A client to test websockets over channels.""" def __init__( self, diff --git a/tests/objects/generics/test_generic_objects.py b/tests/objects/generics/test_generic_objects.py index 3ec5397b84..2dcf9d5fe3 100644 --- a/tests/objects/generics/test_generic_objects.py +++ b/tests/objects/generics/test_generic_objects.py @@ -5,13 +5,13 @@ import pytest import strawberry -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, StrawberryOptional, StrawberryTypeVar, get_object_definition, ) -from strawberry.union import StrawberryUnion +from strawberry.types.union import StrawberryUnion T = TypeVar("T") diff --git a/tests/objects/generics/test_names.py b/tests/objects/generics/test_names.py index 997f01a38c..fe5c747122 100644 --- a/tests/objects/generics/test_names.py +++ b/tests/objects/generics/test_names.py @@ -5,11 +5,11 @@ import pytest import strawberry -from strawberry.enum import EnumDefinition -from strawberry.lazy_type import LazyType from strawberry.schema.config import StrawberryConfig -from strawberry.type import StrawberryList, StrawberryOptional -from strawberry.union import StrawberryUnion +from strawberry.types.base import StrawberryList, StrawberryOptional +from strawberry.types.enum import EnumDefinition +from strawberry.types.lazy_type import LazyType +from strawberry.types.union import StrawberryUnion T = TypeVar("T") K = TypeVar("K") @@ -87,7 +87,8 @@ class Connection(Generic[T]): def test_nested_generics_aliases_with_schema(): """This tests is similar to the previous test, but it also tests against - the schema, since the resolution of the type name might be different.""" + the schema, since the resolution of the type name might be different. + """ config = StrawberryConfig() @strawberry.type diff --git a/tests/python_312/test_generic_objects.py b/tests/python_312/test_generic_objects.py index 026a7d51b5..107218e1fd 100644 --- a/tests/python_312/test_generic_objects.py +++ b/tests/python_312/test_generic_objects.py @@ -8,13 +8,13 @@ import pytest import strawberry -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, StrawberryOptional, StrawberryTypeVar, get_object_definition, ) -from strawberry.union import StrawberryUnion +from strawberry.types.union import StrawberryUnion pytestmark = pytest.mark.skipif( sys.version_info < (3, 12), reason="These are tests for Python 3.12+" diff --git a/tests/python_312/test_python_generics.py b/tests/python_312/test_python_generics.py index 55de842d29..7f3a8b1b90 100644 --- a/tests/python_312/test_python_generics.py +++ b/tests/python_312/test_python_generics.py @@ -1,6 +1,4 @@ -""" -These tests are for Generics that don't expose any generic parts to the schema. -""" +"""These tests are for Generics that don't expose any generic parts to the schema.""" import sys import textwrap diff --git a/tests/relay/test_fields.py b/tests/relay/test_fields.py index 9b13fe9c65..9993697d17 100644 --- a/tests/relay/test_fields.py +++ b/tests/relay/test_fields.py @@ -7,11 +7,11 @@ import strawberry from strawberry import relay from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument -from strawberry.field import StrawberryField from strawberry.relay.fields import ConnectionExtension from strawberry.relay.utils import to_base64 from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY +from strawberry.types.arguments import StrawberryArgument +from strawberry.types.field import StrawberryField from strawberry.types.fields.resolver import StrawberryResolver from .schema import FruitAsync, schema @@ -1597,9 +1597,8 @@ class Query: async def test_query_before_error(): - """ - Verify if the error raised on a non-existing before hash - raises the correct error + """Verify if the error raised on a non-existing before hash + raises the correct error. """ # with pytest.raises(ValueError): index = to_base64("Fake", 9292292) @@ -1612,9 +1611,8 @@ async def test_query_before_error(): def test_query_after_error(): - """ - Verify if the error raised on a non-existing before hash - raises the correct error + """Verify if the error raised on a non-existing before hash + raises the correct error. """ index = to_base64("Fake", 9292292) result = schema.execute_sync( diff --git a/tests/relay/test_utils.py b/tests/relay/test_utils.py index 2b0a925404..e14a375522 100644 --- a/tests/relay/test_utils.py +++ b/tests/relay/test_utils.py @@ -13,7 +13,7 @@ to_base64, ) from strawberry.schema.config import StrawberryConfig -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition from .schema import Fruit diff --git a/tests/schema/extensions/test_extensions.py b/tests/schema/extensions/test_extensions.py index fa7a2cf284..fba3d400b4 100644 --- a/tests/schema/extensions/test_extensions.py +++ b/tests/schema/extensions/test_extensions.py @@ -855,7 +855,6 @@ def ping(self) -> str: def test_extension_execution_order_sync(): """Ensure mixed hooks (async & sync) are called correctly.""" - execution_order: List[Type[SchemaExtension]] = [] class ExtensionB(SchemaExtension): diff --git a/tests/schema/extensions/test_field_extensions.py b/tests/schema/extensions/test_field_extensions.py index a0e741a6b0..eea9e0e1ab 100644 --- a/tests/schema/extensions/test_field_extensions.py +++ b/tests/schema/extensions/test_field_extensions.py @@ -164,9 +164,7 @@ def string(self) -> str: async def test_can_use_sync_only_and_sync_before_async_extensions(): - """ - Use Sync - Sync + Async - Sync - Async possible - """ + """Use Sync - Sync + Async - Sync - Async possible.""" @strawberry.type class Query: @@ -266,9 +264,8 @@ def string(self) -> str: def test_extension_argument_parsing(): - """ - Check that kwargs passed to field extensions have been converted into - Strawberry types + """Check that kwargs passed to field extensions have been converted into + Strawberry types. """ @strawberry.input diff --git a/tests/schema/test_arguments.py b/tests/schema/test_arguments.py index e6932b5321..7c1f2e32f9 100644 --- a/tests/schema/test_arguments.py +++ b/tests/schema/test_arguments.py @@ -4,7 +4,7 @@ from typing_extensions import Annotated import strawberry -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET def test_argument_descriptions(): @@ -221,7 +221,6 @@ def test_argument_parse_order(): Refer to: https://github.com/strawberry-graphql/strawberry/issues/2855 """ - from tests.schema.test_annotated import type_a, type_b expected = """ diff --git a/tests/schema/test_basic.py b/tests/schema/test_basic.py index d3d257037e..47e248f2f8 100644 --- a/tests/schema/test_basic.py +++ b/tests/schema/test_basic.py @@ -10,7 +10,7 @@ from strawberry import ID from strawberry.scalars import Base64 from strawberry.schema_directive import Location -from strawberry.type import StrawberryList +from strawberry.types.base import StrawberryList def test_raises_exception_with_unsupported_types(): @@ -365,7 +365,8 @@ def example(self) -> Schema: def test_can_return_compatible_type(): """Test that we can return a different type that has the same fields, - for example when returning a Django Model.""" + for example when returning a Django Model. + """ @dataclass class Example: diff --git a/tests/schema/test_directives.py b/tests/schema/test_directives.py index 89a33c8464..9c82d483e0 100644 --- a/tests/schema/test_directives.py +++ b/tests/schema/test_directives.py @@ -8,7 +8,7 @@ from strawberry.directive import DirectiveLocation, DirectiveValue from strawberry.extensions import SchemaExtension from strawberry.schema.config import StrawberryConfig -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition from strawberry.utils.await_maybe import await_maybe diff --git a/tests/schema/test_enum.py b/tests/schema/test_enum.py index 8b0df578fa..4c6d566e3c 100644 --- a/tests/schema/test_enum.py +++ b/tests/schema/test_enum.py @@ -7,7 +7,7 @@ import pytest import strawberry -from strawberry.lazy_type import lazy +from strawberry.types.lazy_type import lazy def test_enum_resolver(): diff --git a/tests/schema/test_extensions.py b/tests/schema/test_extensions.py index 2f3895e445..131864142c 100644 --- a/tests/schema/test_extensions.py +++ b/tests/schema/test_extensions.py @@ -14,7 +14,7 @@ from strawberry.scalars import JSON from strawberry.schema.schema_converter import GraphQLCoreConverter from strawberry.schema_directive import Location -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition DEFINITION_BACKREF = GraphQLCoreConverter.DEFINITION_BACKREF diff --git a/tests/schema/test_fields.py b/tests/schema/test_fields.py index 58c58b4cb1..db0b3abe29 100644 --- a/tests/schema/test_fields.py +++ b/tests/schema/test_fields.py @@ -3,9 +3,9 @@ from operator import getitem import strawberry -from strawberry.field import StrawberryField from strawberry.printer import print_schema from strawberry.schema.config import StrawberryConfig +from strawberry.types.field import StrawberryField def test_custom_field(): @@ -84,9 +84,7 @@ class Query: def test_field_type_priority(): - """ - Prioritise the field annotation on the class over the resolver annotation. - """ + """Prioritise the field annotation on the class over the resolver annotation.""" def my_resolver() -> str: return "1.33" diff --git a/tests/schema/test_info.py b/tests/schema/test_info.py index 9fa9ffd347..0c3c23dc3c 100644 --- a/tests/schema/test_info.py +++ b/tests/schema/test_info.py @@ -6,9 +6,9 @@ import pytest import strawberry -from strawberry.type import StrawberryOptional +from strawberry.types.base import StrawberryOptional from strawberry.types.nodes import FragmentSpread, InlineFragment, SelectedField -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET def test_info_has_the_correct_shape(): diff --git a/tests/schema/test_interface.py b/tests/schema/test_interface.py index 4fc37405bc..31f106b09e 100644 --- a/tests/schema/test_interface.py +++ b/tests/schema/test_interface.py @@ -5,7 +5,7 @@ from pytest_mock import MockerFixture import strawberry -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import StrawberryObjectDefinition def test_query_interface(): diff --git a/tests/schema/test_mutation.py b/tests/schema/test_mutation.py index 2671cb3fd4..b41476018b 100644 --- a/tests/schema/test_mutation.py +++ b/tests/schema/test_mutation.py @@ -3,7 +3,7 @@ from textwrap import dedent import strawberry -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET def test_mutation(): diff --git a/tests/schema/test_name_converter.py b/tests/schema/test_name_converter.py index ba22e0b1d0..a406fbd532 100644 --- a/tests/schema/test_name_converter.py +++ b/tests/schema/test_name_converter.py @@ -3,17 +3,16 @@ from typing import Generic, List, Optional, TypeVar, Union import strawberry -from strawberry.arguments import StrawberryArgument -from strawberry.custom_scalar import ScalarDefinition from strawberry.directive import StrawberryDirective -from strawberry.enum import EnumDefinition, EnumValue -from strawberry.field import StrawberryField from strawberry.schema.config import StrawberryConfig from strawberry.schema.name_converter import NameConverter from strawberry.schema_directive import Location, StrawberrySchemaDirective -from strawberry.type import StrawberryType -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion +from strawberry.types.arguments import StrawberryArgument +from strawberry.types.base import StrawberryObjectDefinition, StrawberryType +from strawberry.types.enum import EnumDefinition, EnumValue +from strawberry.types.field import StrawberryField +from strawberry.types.scalar import ScalarDefinition +from strawberry.types.union import StrawberryUnion class AppendsNameConverter(NameConverter): diff --git a/tests/schema/test_private_field.py b/tests/schema/test_private_field.py index 951a21eebf..554f6b59fa 100644 --- a/tests/schema/test_private_field.py +++ b/tests/schema/test_private_field.py @@ -6,7 +6,7 @@ import strawberry from strawberry.annotation import StrawberryAnnotation from strawberry.exceptions import PrivateStrawberryFieldError -from strawberry.field import StrawberryField +from strawberry.types.field import StrawberryField def test_private_field(): @@ -79,7 +79,6 @@ class SensitiveData: def test_private_field_with_str_annotations(): """Check compatibility of strawberry.Private with annotations as string.""" - schema = strawberry.Schema(query=Query) result = schema.execute_sync( @@ -98,7 +97,6 @@ def test_private_field_with_str_annotations(): def test_private_field_defined_outside_module_scope(): """Check compatibility of strawberry.Private when defined outside module scope.""" - global LocallyScopedSensitiveData @strawberry.type @@ -126,7 +124,6 @@ def test_private_field_type_resolution_with_generic_type(): Refer to: https://github.com/strawberry-graphql/strawberry/issues/1938 """ - T = TypeVar("T") class GenericPrivateType(Generic[T]): diff --git a/tests/schema/test_schema_hooks.py b/tests/schema/test_schema_hooks.py index 51038e2f49..c24b352e6e 100644 --- a/tests/schema/test_schema_hooks.py +++ b/tests/schema/test_schema_hooks.py @@ -2,8 +2,8 @@ from typing import List import strawberry -from strawberry.field import StrawberryField -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import StrawberryObjectDefinition +from strawberry.types.field import StrawberryField def test_can_change_which_fields_are_exposed(): diff --git a/tests/schema/test_union.py b/tests/schema/test_union.py index fe8e2ec98f..42392b9584 100644 --- a/tests/schema/test_union.py +++ b/tests/schema/test_union.py @@ -9,7 +9,7 @@ import strawberry from strawberry.exceptions import InvalidUnionTypeError -from strawberry.lazy_type import lazy +from strawberry.types.lazy_type import lazy def test_union_as_field(): @@ -467,8 +467,7 @@ def my_field(self) -> MyUnion: reason="pipe syntax for union is only available on python 3.10+", ) def test_union_optional_with_or_operator(): - """ - Verify that the `|` operator is supported when annotating unions as + """Verify that the `|` operator is supported when annotating unions as optional in schemas. """ @@ -502,9 +501,7 @@ def animal(self) -> animal_union | None: def test_union_with_input_types(): - """ - Verify that union of input types raises an error - """ + """Verify that union of input types raises an error.""" @strawberry.type class User: @@ -538,8 +535,7 @@ def user(self, data: Input) -> User: def test_union_with_similar_nested_generic_types(): - """ - Previously this failed due to an edge case where Strawberry would choose AContainer + """Previously this failed due to an edge case where Strawberry would choose AContainer as the resolved type for container_b due to the inability to exactly match the nested generic `Container.items`. """ @@ -611,9 +607,7 @@ def container_b(self) -> Union[Container[B], B]: def test_lazy_union(): - """ - Previously this failed to evaluate generic parameters on lazy types - """ + """Previously this failed to evaluate generic parameters on lazy types""" TypeA = Annotated["TypeA", lazy("tests.schema.test_lazy_types.type_a")] TypeB = Annotated["TypeB", lazy("tests.schema.test_lazy_types.type_b")] diff --git a/tests/schema/test_union_deprecated.py b/tests/schema/test_union_deprecated.py index 402a24d831..c20695f0b1 100644 --- a/tests/schema/test_union_deprecated.py +++ b/tests/schema/test_union_deprecated.py @@ -215,8 +215,7 @@ def my_field(self) -> MyUnion: reason="pipe syntax for union is only available on python 3.10+", ) def test_union_optional_with_or_operator(): - """ - Verify that the `|` operator is supported when annotating unions as + """Verify that the `|` operator is supported when annotating unions as optional in schemas. """ diff --git a/tests/schema/types/test_date.py b/tests/schema/types/test_date.py index f3232c7a5e..419eac7894 100644 --- a/tests/schema/types/test_date.py +++ b/tests/schema/types/test_date.py @@ -99,11 +99,9 @@ def date_input(self, date_input: datetime.date) -> datetime.date: ), ) def test_serialization_of_incorrect_date_string(value): - """ - Test GraphQLError is raised for incorrect date. + """Test GraphQLError is raised for incorrect date. The error should exclude "original_error". """ - result = execute_mutation(value) assert result.errors assert isinstance(result.errors[0], GraphQLError) @@ -111,11 +109,9 @@ def test_serialization_of_incorrect_date_string(value): def test_serialization_error_message_for_incorrect_date_string(): + """Test if error message is using original error message from + date lib, and is properly formatted. """ - Test if error message is using original error message from - date lib, and is properly formatted - """ - result = execute_mutation("2021-13-01") assert result.errors assert result.errors[0].message == ( diff --git a/tests/schema/types/test_datetime.py b/tests/schema/types/test_datetime.py index 48741f38e6..d07ee654b5 100644 --- a/tests/schema/types/test_datetime.py +++ b/tests/schema/types/test_datetime.py @@ -149,11 +149,9 @@ def datetime_input( ), ) def test_serialization_of_incorrect_datetime_string(value): - """ - Test GraphQLError is raised for incorrect datetime. + """Test GraphQLError is raised for incorrect datetime. The error should exclude "original_error". """ - result = execute_mutation(value) assert result.errors assert isinstance(result.errors[0], GraphQLError) @@ -161,11 +159,9 @@ def test_serialization_of_incorrect_datetime_string(value): def test_serialization_error_message_for_incorrect_datetime_string(): + """Test if error message is using original error message + from datetime lib, and is properly formatted. """ - Test if error message is using original error message - from datetime lib, and is properly formatted - """ - result = execute_mutation("2021-13-01T09:00:00") assert result.errors assert result.errors[0].message == ( diff --git a/tests/schema/types/test_decimal.py b/tests/schema/types/test_decimal.py index 327cfddc92..3651495b33 100644 --- a/tests/schema/types/test_decimal.py +++ b/tests/schema/types/test_decimal.py @@ -36,8 +36,7 @@ def example_decimal(self, decimal: Decimal) -> Decimal: def test_serialization_of_incorrect_decimal_string(): - """ - Test GraphQLError is raised for an invalid Decimal. + """Test GraphQLError is raised for an invalid Decimal. The error should exclude "original_error". """ diff --git a/tests/schema/types/test_time.py b/tests/schema/types/test_time.py index 3f55dd7669..db04469390 100644 --- a/tests/schema/types/test_time.py +++ b/tests/schema/types/test_time.py @@ -98,11 +98,9 @@ def time_input(self, time_input: datetime.time) -> datetime.time: ), ) def test_serialization_of_incorrect_time_string(value): - """ - Test GraphQLError is raised for incorrect time. + """Test GraphQLError is raised for incorrect time. The error should exclude "original_error". """ - result = execute_mutation(value) assert result.errors assert isinstance(result.errors[0], GraphQLError) @@ -110,11 +108,9 @@ def test_serialization_of_incorrect_time_string(value): def test_serialization_error_message_for_incorrect_time_string(): + """Test if error message is using original error message + from time lib, and is properly formatted. """ - Test if error message is using original error message - from time lib, and is properly formatted - """ - result = execute_mutation("25:00") assert result.errors assert result.errors[0].message == ( diff --git a/tests/schema/types/test_uuid.py b/tests/schema/types/test_uuid.py index 6c44b56c05..880d1c5496 100644 --- a/tests/schema/types/test_uuid.py +++ b/tests/schema/types/test_uuid.py @@ -36,8 +36,7 @@ def example_uuid_in(self, uid: uuid.UUID) -> uuid.UUID: def test_serialization_of_incorrect_uuid_string(): - """ - Test GraphQLError is raised for an invalid UUID. + """Test GraphQLError is raised for an invalid UUID. The error should exclude "original_error". """ diff --git a/tests/test_auto.py b/tests/test_auto.py index f181bc78bd..ddeac975e2 100644 --- a/tests/test_auto.py +++ b/tests/test_auto.py @@ -3,8 +3,8 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.auto import StrawberryAuto, auto -from strawberry.type import StrawberryList +from strawberry.types.auto import StrawberryAuto, auto +from strawberry.types.base import StrawberryList @strawberry.type @@ -20,7 +20,7 @@ def test_singleton(): def test_annotated(): assert get_args(auto) == (Any, StrawberryAuto()) some_obj = object() - new_annotated = Annotated[auto, some_obj] + new_annotated = Annotated[strawberry.auto, some_obj] assert get_args(new_annotated) == (Any, StrawberryAuto(), some_obj) @@ -47,7 +47,7 @@ def test_isinstance_with_annotation(): def test_isinstance_with_annotated(): assert isinstance(Annotated[auto, object()], StrawberryAuto) - assert not isinstance(Annotated[str, auto], StrawberryAuto) + assert not isinstance(Annotated[str, strawberry.auto], StrawberryAuto) def test_isinstance_with_unresolvable_annotation(): diff --git a/tests/test_deprecations.py b/tests/test_deprecations.py index 7cf3ec8dae..33e81b949f 100644 --- a/tests/test_deprecations.py +++ b/tests/test_deprecations.py @@ -19,6 +19,6 @@ def test_get_warns(): def test_can_import_type_definition(): - from strawberry.types.types import TypeDefinition + from strawberry.types.base import TypeDefinition assert TypeDefinition diff --git a/tests/test_forward_references.py b/tests/test_forward_references.py index f5b17bda1f..ea771ec9dd 100644 --- a/tests/test_forward_references.py +++ b/tests/test_forward_references.py @@ -11,7 +11,7 @@ import strawberry from strawberry.printer import print_schema from strawberry.scalars import JSON -from strawberry.type import StrawberryList, StrawberryOptional +from strawberry.types.base import StrawberryList, StrawberryOptional from tests.a import A from tests.d import D diff --git a/tests/test_printer/test_basic.py b/tests/test_printer/test_basic.py index 7d4e8070f5..a38d6f0801 100644 --- a/tests/test_printer/test_basic.py +++ b/tests/test_printer/test_basic.py @@ -6,7 +6,7 @@ from strawberry.printer import print_schema from strawberry.scalars import JSON from strawberry.schema.config import StrawberryConfig -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET def test_simple_required_types(): diff --git a/tests/test_printer/test_schema_directives.py b/tests/test_printer/test_schema_directives.py index 1904bd0035..4efe8ab5f2 100644 --- a/tests/test_printer/test_schema_directives.py +++ b/tests/test_printer/test_schema_directives.py @@ -7,7 +7,7 @@ from strawberry.printer import print_schema from strawberry.schema.config import StrawberryConfig from strawberry.schema_directive import Location -from strawberry.unset import UNSET +from strawberry.types.unset import UNSET def test_print_simple_directive(): diff --git a/tests/test_type.py b/tests/test_type.py index 0ef197a2c0..168cab4e21 100644 --- a/tests/test_type.py +++ b/tests/test_type.py @@ -5,8 +5,7 @@ import pytest import strawberry -from strawberry.type import get_object_definition -from strawberry.types.types import StrawberryObjectDefinition +from strawberry.types.base import StrawberryObjectDefinition, get_object_definition def test_get_object_definition(): diff --git a/tests/tools/test_create_type.py b/tests/tools/test_create_type.py index 6e69be5411..5f4f99518e 100644 --- a/tests/tools/test_create_type.py +++ b/tests/tools/test_create_type.py @@ -4,9 +4,9 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.field import StrawberryField from strawberry.tools import create_type -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition +from strawberry.types.field import StrawberryField def test_create_type(): diff --git a/tests/tools/test_merge_types.py b/tests/tools/test_merge_types.py index 7631575217..d342b7ddc6 100644 --- a/tests/tools/test_merge_types.py +++ b/tests/tools/test_merge_types.py @@ -37,7 +37,6 @@ def bye(self, name: str = "world") -> str: def test_custom_name(): """The resulting type should have a custom name is one is specified""" - custom_name = "SuperQuery" ComboQuery = merge_types(custom_name, (ComplexGreeter, Person)) assert ComboQuery.__name__ == custom_name @@ -45,7 +44,6 @@ def test_custom_name(): def test_inheritance(): """It should merge multiple types following the regular inheritance rules""" - ComboQuery = merge_types("SuperType", (ComplexGreeter, Person)) definition = ComboQuery.__strawberry_definition__ @@ -58,14 +56,12 @@ def test_inheritance(): def test_empty_list(): """It should raise when the `types` argument is empty""" - with pytest.raises(ValueError): merge_types("EmptyType", ()) def test_schema(): """It should create a valid, usable schema based on a merged query""" - ComboQuery = merge_types("SuperSchema", (ComplexGreeter, Person)) schema = strawberry.Schema(query=ComboQuery) @@ -90,6 +86,5 @@ def test_schema(): def test_fields_override(): """It should warn when merging results in overriding fields""" - with pytest.warns(Warning): merge_types("FieldsOverride", (ComplexGreeter, SimpleGreeter)) diff --git a/tests/typecheckers/test_type.py b/tests/typecheckers/test_type.py index b673d00da2..8f855231d6 100644 --- a/tests/typecheckers/test_type.py +++ b/tests/typecheckers/test_type.py @@ -7,7 +7,7 @@ CODE = """ import strawberry -from strawberry.type import StrawberryOptional, StrawberryList +from strawberry.types.base import StrawberryOptional, StrawberryList @strawberry.type @@ -86,49 +86,49 @@ def test(): [ Result( type="note", - message='Revealed type is "strawberry.type.StrawberryOptional"', + message='Revealed type is "strawberry.types.base.StrawberryOptional"', line=11, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryList"', + message='Revealed type is "strawberry.types.base.StrawberryList"', line=12, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryOptional"', + message='Revealed type is "strawberry.types.base.StrawberryOptional"', line=13, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryList"', + message='Revealed type is "strawberry.types.base.StrawberryList"', line=14, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryOptional"', + message='Revealed type is "strawberry.types.base.StrawberryOptional"', line=16, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryList"', + message='Revealed type is "strawberry.types.base.StrawberryList"', line=17, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryOptional"', + message='Revealed type is "strawberry.types.base.StrawberryOptional"', line=18, column=13, ), Result( type="note", - message='Revealed type is "strawberry.type.StrawberryList"', + message='Revealed type is "strawberry.types.base.StrawberryList"', line=19, column=13, ), diff --git a/tests/typecheckers/test_union.py b/tests/typecheckers/test_union.py index f48969469c..66df1365f7 100644 --- a/tests/typecheckers/test_union.py +++ b/tests/typecheckers/test_union.py @@ -39,7 +39,7 @@ def test(): [ Result( type="information", - message='Type of "UserOrError" is "type[User] | type[Error]"', + message='Type of "UserOrError" is "type[Annotated]"', line=19, column=13, ), diff --git a/tests/typecheckers/utils/mypy.py b/tests/typecheckers/utils/mypy.py index 6fa0cef2d7..d78caa3f07 100644 --- a/tests/typecheckers/utils/mypy.py +++ b/tests/typecheckers/utils/mypy.py @@ -64,16 +64,20 @@ def run_mypy(code: str, strict: bool = True) -> List[Result]: results: List[Result] = [] - for line in full_output.split("\n"): - mypy_result = json.loads(line) - results.append( - Result( - type=mypy_result["severity"].strip(), - message=mypy_result["message"].strip(), - line=mypy_result["line"], - column=mypy_result["column"] + 1, + try: + for line in full_output.split("\n"): + mypy_result = json.loads(line) + + results.append( + Result( + type=mypy_result["severity"].strip(), + message=mypy_result["message"].strip(), + line=mypy_result["line"], + column=mypy_result["column"] + 1, + ) ) - ) + except json.JSONDecodeError: + raise Exception(f"Invalid JSON: {full_output}") results.sort(key=lambda x: (x.line, x.column, x.message)) diff --git a/tests/types/cross_module_resolvers/test_cross_module_resolvers.py b/tests/types/cross_module_resolvers/test_cross_module_resolvers.py index 1a7686485b..4c218319f8 100644 --- a/tests/types/cross_module_resolvers/test_cross_module_resolvers.py +++ b/tests/types/cross_module_resolvers/test_cross_module_resolvers.py @@ -1,5 +1,4 @@ -""" -The following tests ensure that the types are resolved using the correct +"""The following tests ensure that the types are resolved using the correct module. Concrete types should be non-problematic and are only included here for completeness. A problematic case is when a type is a string (forward reference) and can only be resolved at schema construction. diff --git a/tests/types/resolving/test_generics.py b/tests/types/resolving/test_generics.py index 2641358924..9c10f8cc73 100644 --- a/tests/types/resolving/test_generics.py +++ b/tests/types/resolving/test_generics.py @@ -5,17 +5,17 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.enum import EnumDefinition -from strawberry.field import StrawberryField -from strawberry.type import ( +from strawberry.types.base import ( StrawberryList, + StrawberryObjectDefinition, StrawberryOptional, StrawberryTypeVar, get_object_definition, has_object_definition, ) -from strawberry.types.types import StrawberryObjectDefinition -from strawberry.union import StrawberryUnion +from strawberry.types.enum import EnumDefinition +from strawberry.types.field import StrawberryField +from strawberry.types.union import StrawberryUnion def test_basic_generic(): diff --git a/tests/types/resolving/test_lists.py b/tests/types/resolving/test_lists.py index b8014fd5ac..c3e50cba1d 100644 --- a/tests/types/resolving/test_lists.py +++ b/tests/types/resolving/test_lists.py @@ -6,7 +6,7 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.type import StrawberryList +from strawberry.types.base import StrawberryList def test_basic_list(): diff --git a/tests/types/resolving/test_optionals.py b/tests/types/resolving/test_optionals.py index cd6ab4b370..3127d0caaf 100644 --- a/tests/types/resolving/test_optionals.py +++ b/tests/types/resolving/test_optionals.py @@ -2,8 +2,8 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.type import StrawberryOptional -from strawberry.unset import UnsetType +from strawberry.types.base import StrawberryOptional +from strawberry.types.unset import UnsetType def test_basic_optional(): diff --git a/tests/types/resolving/test_string_annotations.py b/tests/types/resolving/test_string_annotations.py index 0bef01a316..321384b7e4 100644 --- a/tests/types/resolving/test_string_annotations.py +++ b/tests/types/resolving/test_string_annotations.py @@ -2,7 +2,11 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.type import StrawberryList, StrawberryOptional, StrawberryTypeVar +from strawberry.types.base import ( + StrawberryList, + StrawberryOptional, + StrawberryTypeVar, +) def test_basic_string(): diff --git a/tests/types/resolving/test_union_pipe.py b/tests/types/resolving/test_union_pipe.py index 5571b4cea4..37e0253c80 100644 --- a/tests/types/resolving/test_union_pipe.py +++ b/tests/types/resolving/test_union_pipe.py @@ -8,8 +8,8 @@ from strawberry.annotation import StrawberryAnnotation from strawberry.exceptions.invalid_union_type import InvalidUnionTypeError from strawberry.schema.types.base_scalars import Date, DateTime -from strawberry.type import StrawberryOptional -from strawberry.union import StrawberryUnion +from strawberry.types.base import StrawberryOptional +from strawberry.types.union import StrawberryUnion pytestmark = pytest.mark.skipif( sys.version_info < (3, 10), diff --git a/tests/types/resolving/test_unions.py b/tests/types/resolving/test_unions.py index 627c138ab1..dee6ecb39d 100644 --- a/tests/types/resolving/test_unions.py +++ b/tests/types/resolving/test_unions.py @@ -7,8 +7,8 @@ import strawberry from strawberry.annotation import StrawberryAnnotation from strawberry.exceptions import InvalidUnionTypeError -from strawberry.type import get_object_definition -from strawberry.union import StrawberryUnion, union +from strawberry.types.base import get_object_definition +from strawberry.types.union import StrawberryUnion, union def test_python_union(): diff --git a/tests/types/resolving/test_unions_deprecated.py b/tests/types/resolving/test_unions_deprecated.py index 7166e57175..640bcef382 100644 --- a/tests/types/resolving/test_unions_deprecated.py +++ b/tests/types/resolving/test_unions_deprecated.py @@ -6,7 +6,7 @@ import strawberry from strawberry.annotation import StrawberryAnnotation from strawberry.exceptions import InvalidUnionTypeError -from strawberry.union import StrawberryUnion, union +from strawberry.types.union import StrawberryUnion, union pytestmark = pytest.mark.filterwarnings( "ignore:Passing types to `strawberry.union` is deprecated." diff --git a/tests/types/test_annotation.py b/tests/types/test_annotation.py index f242480d46..6ca9076642 100644 --- a/tests/types/test_annotation.py +++ b/tests/types/test_annotation.py @@ -6,7 +6,7 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.unset import UnsetType +from strawberry.types.unset import UnsetType class Bleh: diff --git a/tests/types/test_field_types.py b/tests/types/test_field_types.py index 27bcea32bb..fab4df79ef 100644 --- a/tests/types/test_field_types.py +++ b/tests/types/test_field_types.py @@ -3,8 +3,8 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.field import StrawberryField -from strawberry.union import StrawberryUnion +from strawberry.types.field import StrawberryField +from strawberry.types.union import StrawberryUnion def test_enum(): diff --git a/tests/types/test_lazy_types.py b/tests/types/test_lazy_types.py index 65e0afff5e..348e86bdbb 100644 --- a/tests/types/test_lazy_types.py +++ b/tests/types/test_lazy_types.py @@ -5,11 +5,11 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.field import StrawberryField -from strawberry.lazy_type import LazyType -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition +from strawberry.types.field import StrawberryField from strawberry.types.fields.resolver import StrawberryResolver -from strawberry.union import StrawberryUnion, union +from strawberry.types.lazy_type import LazyType +from strawberry.types.union import StrawberryUnion, union T = TypeVar("T") diff --git a/tests/types/test_object_types.py b/tests/types/test_object_types.py index 5ad782a830..444d3160ad 100644 --- a/tests/types/test_object_types.py +++ b/tests/types/test_object_types.py @@ -8,8 +8,8 @@ import pytest import strawberry -from strawberry.field import StrawberryField -from strawberry.type import get_object_definition +from strawberry.types.base import get_object_definition +from strawberry.types.field import StrawberryField def test_enum(): diff --git a/tests/utils/test_arguments_converter.py b/tests/utils/test_arguments_converter.py index 7d64e10a00..cb8f9e26ed 100644 --- a/tests/utils/test_arguments_converter.py +++ b/tests/utils/test_arguments_converter.py @@ -6,12 +6,12 @@ import strawberry from strawberry.annotation import StrawberryAnnotation -from strawberry.arguments import StrawberryArgument, convert_arguments from strawberry.exceptions import UnsupportedTypeError -from strawberry.lazy_type import LazyType from strawberry.schema.config import StrawberryConfig from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY -from strawberry.unset import UNSET +from strawberry.types.arguments import StrawberryArgument, convert_arguments +from strawberry.types.lazy_type import LazyType +from strawberry.types.unset import UNSET def test_simple_types(): diff --git a/tests/utils/test_typing.py b/tests/utils/test_typing.py index b379f30382..bf8809bc3d 100644 --- a/tests/utils/test_typing.py +++ b/tests/utils/test_typing.py @@ -6,7 +6,7 @@ import pytest import strawberry -from strawberry.lazy_type import LazyType +from strawberry.types.lazy_type import LazyType from strawberry.utils.typing import eval_type, get_optional_annotation, is_classvar diff --git a/tests/websockets/test_graphql_transport_ws.py b/tests/websockets/test_graphql_transport_ws.py index 1ab738fb73..2b38108adc 100644 --- a/tests/websockets/test_graphql_transport_ws.py +++ b/tests/websockets/test_graphql_transport_ws.py @@ -312,9 +312,8 @@ async def test_duplicated_operation_ids(ws: WebSocketClient): async def test_reused_operation_ids(ws: WebSocketClient): - """ - Test that an operation id can be re-used after it has been - previously used for a completed operation + """Test that an operation id can be re-used after it has been + previously used for a completed operation. """ # Use sub1 as an id for an operation await ws.send_json( @@ -480,9 +479,7 @@ async def test_subscription_errors(ws: WebSocketClient): async def test_operation_error_no_complete(ws: WebSocketClient): - """ - Test that an "error" message is not followed by "complete" - """ + """Test that an "error" message is not followed by "complete".""" # get an "error" message await ws.send_json( SubscribeMessage( @@ -553,10 +550,9 @@ async def test_single_result_query_operation(ws: WebSocketClient): async def test_single_result_query_operation_async(ws: WebSocketClient): - """ - Test a single result query operation on an + """Test a single result query operation on an `async` method in the schema, including an artificial - async delay + async delay. """ await ws.send_json( SubscribeMessage( @@ -580,8 +576,7 @@ async def test_single_result_query_operation_async(ws: WebSocketClient): async def test_single_result_query_operation_overlapped(ws: WebSocketClient): - """ - Test that two single result queries can be in flight at the same time, + """Test that two single result queries can be in flight at the same time, just like regular queries. Start two queries with separate ids. The first query has a delay, so we expect the response to the second query to be delivered first. @@ -705,9 +700,8 @@ async def test_single_result_operation_error(ws: WebSocketClient): async def test_single_result_operation_exception(ws: WebSocketClient): - """ - Test that single-result-operations which raise exceptions - behave in the same way as streaming operations + """Test that single-result-operations which raise exceptions + behave in the same way as streaming operations. """ process_errors = Mock() with patch.object(Schema, "process_errors", process_errors): @@ -730,9 +724,8 @@ async def test_single_result_operation_exception(ws: WebSocketClient): async def test_single_result_duplicate_ids_sub(ws: WebSocketClient): - """ - Test that single-result-operations and streaming operations - share the same ID namespace. Start a regular subscription, + """Test that single-result-operations and streaming operations + share the same ID namespace. Start a regular subscription, then issue a single-result operation with same ID and expect an error due to already existing ID """ @@ -762,10 +755,9 @@ async def test_single_result_duplicate_ids_sub(ws: WebSocketClient): async def test_single_result_duplicate_ids_query(ws: WebSocketClient): - """ - Test that single-result-operations don't allow duplicate - IDs for two asynchronous queries. Issue one async query - with delay, then another with same id. Expect error. + """Test that single-result-operations don't allow duplicate + IDs for two asynchronous queries. Issue one async query + with delay, then another with same id. Expect error. """ # single result subscription 1 await ws.send_json( @@ -890,9 +882,8 @@ async def test_subsciption_cancel_finalization_delay(ws: WebSocketClient): async def test_error_handler_for_timeout(http_client: HttpClient): - """ - Test that the error handler is called when the timeout - task encounters an error + """Test that the error handler is called when the timeout + task encounters an error. """ with contextlib.suppress(ImportError): from tests.http.clients.channels import ChannelsHttpClient @@ -936,9 +927,8 @@ def on_init(_handler): async def test_subscription_errors_continue(ws: WebSocketClient): - """ - Verify that an ExecutionResult with errors during subscription does not terminate - the subscription + """Verify that an ExecutionResult with errors during subscription does not terminate + the subscription. """ process_errors = Mock() with patch.object(Schema, "process_errors", process_errors):