From 7ed25c1a7d6199365b552d73f8aabbd807865c9b Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:27:42 +0530 Subject: [PATCH 1/6] feat!: AniList.get() now accepts every parameter accepted by anilist BREAKING CHANGE: .search() is removed because it was redundant --- docs/api-reference/enums.md | 1 + docs/api-reference/exceptions.md | 119 +------ docs/api-reference/types.md | 15 +- mkdocs.yml | 5 +- poetry.lock | 197 +++++++----- pyproject.toml | 2 +- src/pyanilist/__init__.py | 69 +--- src/pyanilist/_clients/__init__.py | 2 + src/pyanilist/_clients/_async.py | 497 ++++++++++++++++------------- src/pyanilist/_clients/_sync.py | 495 ++++++++++++++++------------ src/pyanilist/_compat.py | 1 + src/pyanilist/_enums.py | 47 +++ src/pyanilist/_exceptions.py | 67 ---- src/pyanilist/_models.py | 20 +- src/pyanilist/_parser.py | 125 ++++++++ src/pyanilist/_query.py | 145 ++++++++- src/pyanilist/_types.py | 30 +- src/pyanilist/_utils.py | 88 +++++ src/pyanilist/_version.py | 12 +- tests/test_anilist.py | 29 +- tests/test_async_anilist.py | 29 +- tests/test_async_exceptions.py | 6 +- tests/test_exceptions.py | 6 +- tests/test_models.py | 7 +- 24 files changed, 1167 insertions(+), 847 deletions(-) delete mode 100644 src/pyanilist/_exceptions.py create mode 100644 src/pyanilist/_parser.py diff --git a/docs/api-reference/enums.md b/docs/api-reference/enums.md index c2a331a..26fda4b 100644 --- a/docs/api-reference/enums.md +++ b/docs/api-reference/enums.md @@ -5,6 +5,7 @@ ::: pyanilist._enums.MediaRankType ::: pyanilist._enums.MediaRelation ::: pyanilist._enums.MediaSeason +::: pyanilist._enums.MediaSort ::: pyanilist._enums.MediaSource ::: pyanilist._enums.MediaStatus ::: pyanilist._enums.MediaType \ No newline at end of file diff --git a/docs/api-reference/exceptions.md b/docs/api-reference/exceptions.md index 03e9f18..c6ad7ae 100644 --- a/docs/api-reference/exceptions.md +++ b/docs/api-reference/exceptions.md @@ -1,117 +1,4 @@ -!!! note - PyAniList simply re-exports exceptions from - [`httpx`](https://www.python-httpx.org/exceptions/) and - [`pydantic`](https://docs.pydantic.dev/latest/api/pydantic_core/#pydantic_core.ValidationError) for convenience. +PyAniList doesn't raise any custom exceptions of it's own. The two most likely errors you'll encounter will be either of these: -::: pyanilist._exceptions.CloseError - options: - show_source: false - members: false -::: pyanilist._exceptions.ConnectError - options: - show_source: false - members: false -::: pyanilist._exceptions.ConnectTimeout - options: - show_source: false - members: false -::: pyanilist._exceptions.CookieConflict - options: - show_source: false - members: false -::: pyanilist._exceptions.DecodingError - options: - show_source: false - members: false -::: pyanilist._exceptions.HTTPError - options: - show_source: false - members: false -::: pyanilist._exceptions.HTTPStatusError - options: - show_source: false - members: false -::: pyanilist._exceptions.InvalidURL - options: - show_source: false - members: false -::: pyanilist._exceptions.LocalProtocolError - options: - show_source: false - members: false -::: pyanilist._exceptions.NetworkError - options: - show_source: false - members: false -::: pyanilist._exceptions.PoolTimeout - options: - show_source: false - members: false -::: pyanilist._exceptions.ProtocolError - options: - show_source: false - members: false -::: pyanilist._exceptions.ProxyError - options: - show_source: false - members: false -::: pyanilist._exceptions.ReadError - options: - show_source: false - members: false -::: pyanilist._exceptions.ReadTimeout - options: - show_source: false - members: false -::: pyanilist._exceptions.RemoteProtocolError - options: - show_source: false - members: false -::: pyanilist._exceptions.RequestError - options: - show_source: false - members: false -::: pyanilist._exceptions.RequestNotRead - options: - show_source: false - members: false -::: pyanilist._exceptions.ResponseNotRead - options: - show_source: false - members: false -::: pyanilist._exceptions.StreamClosed - options: - show_source: false - members: false -::: pyanilist._exceptions.StreamConsumed - options: - show_source: false - members: false -::: pyanilist._exceptions.StreamError - options: - show_source: false - members: false -::: pyanilist._exceptions.TimeoutException - options: - show_source: false - members: false -::: pyanilist._exceptions.TooManyRedirects - options: - show_source: false - members: false -::: pyanilist._exceptions.UnsupportedProtocol - options: - show_source: false - members: false -::: pyanilist._exceptions.WriteError - options: - show_source: false - members: false -::: pyanilist._exceptions.WriteTimeout - options: - show_source: false - members: false -::: pyanilist._exceptions.ValidationError - options: - show_source: false - members: false \ No newline at end of file +- `pyanilist.HTTPStatusError` - Alias for [`httpx.HTTPStatusError`](https://www.python-httpx.org/exceptions/). Raised if a request returns a non 2xx status code. +- `pyanilist.ValidationError` - Alias for [`pydantic.ValidationError`](https://docs.pydantic.dev/latest/errors/validation_errors/). Raised if an input is invalid. diff --git a/docs/api-reference/types.md b/docs/api-reference/types.md index bb124b3..d5a1a49 100644 --- a/docs/api-reference/types.md +++ b/docs/api-reference/types.md @@ -1,15 +1,2 @@ -!!! note - Additionally, PyAniList also uses and exports the following [pydantic](https://docs.pydantic.dev/latest/) types for convenience: - - - [HttpUrl](https://docs.pydantic.dev/latest/api/networks/#pydantic.networks.HttpUrl) - - - [Color](https://docs.pydantic.dev/latest/api/pydantic_extra_types_color/#pydantic_extra_types.color.Color) - - - [CountryAlpha2 as CountryCode](https://docs.pydantic.dev/latest/api/pydantic_extra_types_country/#pydantic_extra_types.country.CountryAlpha2) - -::: pyanilist._types.AniListID -::: pyanilist._types.AniListTitle -::: pyanilist._types.AniListYear ::: pyanilist._types.YearsActive -::: pyanilist._types.HTTPXAsyncClientKwargs -::: pyanilist._types.HTTPXClientKwargs +::: pyanilist._types.FuzzyDateInt diff --git a/mkdocs.yml b/mkdocs.yml index a9d1a64..c6dcc99 100644 --- a/mkdocs.yml +++ b/mkdocs.yml @@ -47,7 +47,6 @@ plugins: options: allow_inspection: false docstring_style: numpy - members: true show_root_heading: true show_root_full_path: false show_signature_annotations: true @@ -56,9 +55,7 @@ plugins: show_symbol_type_toc: true signature_crossrefs: true merge_init_into_class: true - preload_modules: - - httpx - - pydantic + filters: ["!^_", "^__init__$"] markdown_extensions: - md_in_html diff --git a/poetry.lock b/poetry.lock index cfd36c0..8fa481f 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -923,109 +923,121 @@ files = [ [[package]] name = "pydantic" -version = "2.7.1" +version = "2.8.0" 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.0-py3-none-any.whl", hash = "sha256:ead4f3a1e92386a734ca1411cb25d94147cf8778ed5be6b56749047676d6364e"}, + {file = "pydantic-2.8.0.tar.gz", hash = "sha256:d970ffb9d030b710795878940bd0489842c638e7252fc4a19c3ae2f7da4d6141"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.18.2" -typing-extensions = ">=4.6.1" +pydantic-core = "2.20.0" +typing-extensions = [ + {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, + {version = ">=4.6.1", markers = "python_version < \"3.13\""}, +] [package.extras] email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.18.2" +version = "2.20.0" 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.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:e9dcd7fb34f7bfb239b5fa420033642fff0ad676b765559c3737b91f664d4fa9"}, + {file = "pydantic_core-2.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:649a764d9b0da29816889424697b2a3746963ad36d3e0968784ceed6e40c6355"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7701df088d0b05f3460f7ba15aec81ac8b0fb5690367dfd072a6c38cf5b7fdb5"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab760f17c3e792225cdaef31ca23c0aea45c14ce80d8eff62503f86a5ab76bff"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cb1ad5b4d73cde784cf64580166568074f5ccd2548d765e690546cff3d80937d"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b81ec2efc04fc1dbf400647d4357d64fb25543bae38d2d19787d69360aad21c9"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4a9732a5cad764ba37f3aa873dccb41b584f69c347a57323eda0930deec8e10"}, + {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6dc85b9e10cc21d9c1055f15684f76fa4facadddcb6cd63abab702eb93c98943"}, + {file = "pydantic_core-2.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:21d9f7e24f63fdc7118e6cc49defaab8c1d27570782f7e5256169d77498cf7c7"}, + {file = "pydantic_core-2.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8b315685832ab9287e6124b5d74fc12dda31e6421d7f6b08525791452844bc2d"}, + {file = "pydantic_core-2.20.0-cp310-none-win32.whl", hash = "sha256:c3dc8ec8b87c7ad534c75b8855168a08a7036fdb9deeeed5705ba9410721c84d"}, + {file = "pydantic_core-2.20.0-cp310-none-win_amd64.whl", hash = "sha256:85770b4b37bb36ef93a6122601795231225641003e0318d23c6233c59b424279"}, + {file = "pydantic_core-2.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:58e251bb5a5998f7226dc90b0b753eeffa720bd66664eba51927c2a7a2d5f32c"}, + {file = "pydantic_core-2.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:78d584caac52c24240ef9ecd75de64c760bbd0e20dbf6973631815e3ef16ef8b"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5084ec9721f82bef5ff7c4d1ee65e1626783abb585f8c0993833490b63fe1792"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d0f52684868db7c218437d260e14d37948b094493f2646f22d3dda7229bbe3f"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1def125d59a87fe451212a72ab9ed34c118ff771e5473fef4f2f95d8ede26d75"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b34480fd6778ab356abf1e9086a4ced95002a1e195e8d2fd182b0def9d944d11"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d42669d319db366cb567c3b444f43caa7ffb779bf9530692c6f244fc635a41eb"}, + {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:53b06aea7a48919a254b32107647be9128c066aaa6ee6d5d08222325f25ef175"}, + {file = "pydantic_core-2.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1f038156b696a1c39d763b2080aeefa87ddb4162c10aa9fabfefffc3dd8180fa"}, + {file = "pydantic_core-2.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3f0f3a4a23717280a5ee3ac4fb1f81d6fde604c9ec5100f7f6f987716bb8c137"}, + {file = "pydantic_core-2.20.0-cp311-none-win32.whl", hash = "sha256:316fe7c3fec017affd916a0c83d6f1ec697cbbbdf1124769fa73328e7907cc2e"}, + {file = "pydantic_core-2.20.0-cp311-none-win_amd64.whl", hash = "sha256:2d06a7fa437f93782e3f32d739c3ec189f82fca74336c08255f9e20cea1ed378"}, + {file = "pydantic_core-2.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d6f8c49657f3eb7720ed4c9b26624063da14937fc94d1812f1e04a2204db3e17"}, + {file = "pydantic_core-2.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad1bd2f377f56fec11d5cfd0977c30061cd19f4fa199bf138b200ec0d5e27eeb"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed741183719a5271f97d93bbcc45ed64619fa38068aaa6e90027d1d17e30dc8d"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d82e5ed3a05f2dcb89c6ead2fd0dbff7ac09bc02c1b4028ece2d3a3854d049ce"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2ba34a099576234671f2e4274e5bc6813b22e28778c216d680eabd0db3f7dad"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:879ae6bb08a063b3e1b7ac8c860096d8fd6b48dd9b2690b7f2738b8c835e744b"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0eefc7633a04c0694340aad91fbfd1986fe1a1e0c63a22793ba40a18fcbdc8"}, + {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73deadd6fd8a23e2f40b412b3ac617a112143c8989a4fe265050fd91ba5c0608"}, + {file = "pydantic_core-2.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:35681445dc85446fb105943d81ae7569aa7e89de80d1ca4ac3229e05c311bdb1"}, + {file = "pydantic_core-2.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0f6dd3612a3b9f91f2e63924ea18a4476656c6d01843ca20a4c09e00422195af"}, + {file = "pydantic_core-2.20.0-cp312-none-win32.whl", hash = "sha256:7e37b6bb6e90c2b8412b06373c6978d9d81e7199a40e24a6ef480e8acdeaf918"}, + {file = "pydantic_core-2.20.0-cp312-none-win_amd64.whl", hash = "sha256:7d4df13d1c55e84351fab51383520b84f490740a9f1fec905362aa64590b7a5d"}, + {file = "pydantic_core-2.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d43e7ab3b65e4dc35a7612cfff7b0fd62dce5bc11a7cd198310b57f39847fd6c"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b6a24d7b5893392f2b8e3b7a0031ae3b14c6c1942a4615f0d8794fdeeefb08b"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2f13c3e955a087c3ec86f97661d9f72a76e221281b2262956af381224cfc243"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72432fd6e868c8d0a6849869e004b8bcae233a3c56383954c228316694920b38"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d70a8ff2d4953afb4cbe6211f17268ad29c0b47e73d3372f40e7775904bc28fc"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e49524917b8d3c2f42cd0d2df61178e08e50f5f029f9af1f402b3ee64574392"}, + {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4f0f71653b1c1bad0350bc0b4cc057ab87b438ff18fa6392533811ebd01439c"}, + {file = "pydantic_core-2.20.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:16197e6f4fdecb9892ed2436e507e44f0a1aa2cff3b9306d1c879ea2f9200997"}, + {file = "pydantic_core-2.20.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:763602504bf640b3ded3bba3f8ed8a1cc2fc6a87b8d55c1c5689f428c49c947e"}, + {file = "pydantic_core-2.20.0-cp313-none-win32.whl", hash = "sha256:a3f243f318bd9523277fa123b3163f4c005a3e8619d4b867064de02f287a564d"}, + {file = "pydantic_core-2.20.0-cp313-none-win_amd64.whl", hash = "sha256:03aceaf6a5adaad3bec2233edc5a7905026553916615888e53154807e404545c"}, + {file = "pydantic_core-2.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d6f2d8b8da1f03f577243b07bbdd3412eee3d37d1f2fd71d1513cbc76a8c1239"}, + {file = "pydantic_core-2.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a272785a226869416c6b3c1b7e450506152d3844207331f02f27173562c917e0"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efbb412d55a4ffe73963fed95c09ccb83647ec63b711c4b3752be10a56f0090b"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e4f46189d8740561b43655263a41aac75ff0388febcb2c9ec4f1b60a0ec12f3"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3df115f4a3c8c5e4d5acf067d399c6466d7e604fc9ee9acbe6f0c88a0c3cf"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a340d2bdebe819d08f605e9705ed551c3feb97e4fd71822d7147c1e4bdbb9508"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:616b9c2f882393d422ba11b40e72382fe975e806ad693095e9a3b67c59ea6150"}, + {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25c46bb2ff6084859bbcfdf4f1a63004b98e88b6d04053e8bf324e115398e9e7"}, + {file = "pydantic_core-2.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:23425eccef8f2c342f78d3a238c824623836c6c874d93c726673dbf7e56c78c0"}, + {file = "pydantic_core-2.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:52527e8f223ba29608d999d65b204676398009725007c9336651c2ec2d93cffc"}, + {file = "pydantic_core-2.20.0-cp38-none-win32.whl", hash = "sha256:1c3c5b7f70dd19a6845292b0775295ea81c61540f68671ae06bfe4421b3222c2"}, + {file = "pydantic_core-2.20.0-cp38-none-win_amd64.whl", hash = "sha256:8093473d7b9e908af1cef30025609afc8f5fd2a16ff07f97440fd911421e4432"}, + {file = "pydantic_core-2.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ee7785938e407418795e4399b2bf5b5f3cf6cf728077a7f26973220d58d885cf"}, + {file = "pydantic_core-2.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e75794883d635071cf6b4ed2a5d7a1e50672ab7a051454c76446ef1ebcdcc91"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:344e352c96e53b4f56b53d24728217c69399b8129c16789f70236083c6ceb2ac"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:978d4123ad1e605daf1ba5e01d4f235bcf7b6e340ef07e7122e8e9cfe3eb61ab"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c05eaf6c863781eb834ab41f5963604ab92855822a2062897958089d1335dad"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc7e43b4a528ffca8c9151b6a2ca34482c2fdc05e6aa24a84b7f475c896fc51d"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658287a29351166510ebbe0a75c373600cc4367a3d9337b964dada8d38bcc0f4"}, + {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1dacf660d6de692fe351e8c806e7efccf09ee5184865893afbe8e59be4920b4a"}, + {file = "pydantic_core-2.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e147fc6e27b9a487320d78515c5f29798b539179f7777018cedf51b7749e4f4"}, + {file = "pydantic_core-2.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c867230d715a3dd1d962c8d9bef0d3168994ed663e21bf748b6e3a529a129aab"}, + {file = "pydantic_core-2.20.0-cp39-none-win32.whl", hash = "sha256:22b813baf0dbf612752d8143a2dbf8e33ccb850656b7850e009bad2e101fc377"}, + {file = "pydantic_core-2.20.0-cp39-none-win_amd64.whl", hash = "sha256:3a7235b46c1bbe201f09b6f0f5e6c36b16bad3d0532a10493742f91fbdc8035f"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cafde15a6f7feaec2f570646e2ffc5b73412295d29134a29067e70740ec6ee20"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2aec8eeea0b08fd6bc2213d8e86811a07491849fd3d79955b62d83e32fa2ad5f"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:840200827984f1c4e114008abc2f5ede362d6e11ed0b5931681884dd41852ff1"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ea1d8b7df522e5ced34993c423c3bf3735c53df8b2a15688a2f03a7d678800"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5b8376a867047bf08910573deb95d3c8dfb976eb014ee24f3b5a61ccc5bee1b"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d08264b4460326cefacc179fc1411304d5af388a79910832835e6f641512358b"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7a3639011c2e8a9628466f616ed7fb413f30032b891898e10895a0a8b5857d6c"}, + {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:05e83ce2f7eba29e627dd8066aa6c4c0269b2d4f889c0eba157233a353053cea"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:603a843fea76a595c8f661cd4da4d2281dff1e38c4a836a928eac1a2f8fe88e4"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac76f30d5d3454f4c28826d891fe74d25121a346c69523c9810ebba43f3b1cec"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e3b1d4b1b3f6082849f9b28427ef147a5b46a6132a3dbaf9ca1baa40c88609"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2761f71faed820e25ec62eacba670d1b5c2709bb131a19fcdbfbb09884593e5a"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0586cddbf4380e24569b8a05f234e7305717cc8323f50114dfb2051fcbce2a3"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b8c46a8cf53e849eea7090f331ae2202cd0f1ceb090b00f5902c423bd1e11805"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b4a085bd04af7245e140d1b95619fe8abb445a3d7fdf219b3f80c940853268ef"}, + {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:116b326ac82c8b315e7348390f6d30bcfe6e688a7d3f1de50ff7bcc2042a23c2"}, + {file = "pydantic_core-2.20.0.tar.gz", hash = "sha256:366be8e64e0cb63d87cf79b4e1765c0703dd6313c729b22e7b9e378db6b96877"}, ] [package.dependencies] @@ -1464,6 +1476,17 @@ files = [ {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, ] +[[package]] +name = "typing-extensions" +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.2-py3-none-any.whl", hash = "sha256:04e5ca0351e0f3f85c6853954072df659d0d13fac324d0072316b67d7794700d"}, + {file = "typing_extensions-4.12.2.tar.gz", hash = "sha256:1a7ead55c7e559dd4dee8856e3a88b41225abfe1ce8df57b7c13915fe121ffb8"}, +] + [[package]] name = "urllib3" version = "2.2.1" @@ -1560,4 +1583,4 @@ testing = ["big-O", "jaraco.functools", "jaraco.itertools", "more-itertools", "p [metadata] lock-version = "2.0" python-versions = ">=3.9" -content-hash = "33b8e5e4f5ea85fdc3e362575eff7506824b6f6d60231145992ee6122446b0f9" +content-hash = "ea0748c83bcfb50bb02f0e5394a95f80d7730f8e7f622989675246ae5448d32f" diff --git a/pyproject.toml b/pyproject.toml index d4d19c9..c06b63f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,7 +22,7 @@ classifiers = [ [tool.poetry.dependencies] python = ">=3.9" -pydantic = ">=2.7.1" +pydantic = "^2.8.0" typing-extensions =">=4.11.0" pydantic-extra-types =">=2.7.0" pycountry = ">=23.12.11" diff --git a/src/pyanilist/__init__.py b/src/pyanilist/__init__.py index 61b9e67..1f39b2c 100644 --- a/src/pyanilist/__init__.py +++ b/src/pyanilist/__init__.py @@ -1,3 +1,8 @@ +from __future__ import annotations + +from httpx import HTTPStatusError +from pydantic import ValidationError + from ._clients import AniList, AsyncAniList from ._enums import ( CharacterRole, @@ -10,36 +15,6 @@ MediaStatus, MediaType, ) -from ._exceptions import ( - CloseError, - ConnectError, - ConnectTimeout, - CookieConflict, - DecodingError, - HTTPError, - HTTPStatusError, - InvalidURL, - LocalProtocolError, - NetworkError, - PoolTimeout, - ProtocolError, - ProxyError, - ReadError, - ReadTimeout, - RemoteProtocolError, - RequestError, - RequestNotRead, - ResponseNotRead, - StreamClosed, - StreamConsumed, - StreamError, - TimeoutException, - TooManyRedirects, - UnsupportedProtocol, - ValidationError, - WriteError, - WriteTimeout, -) from ._models import ( AiringSchedule, Character, @@ -61,7 +36,7 @@ StaffName, Studio, ) -from ._types import AniListID, AniListTitle, AniListYear, Color, CountryCode, HttpUrl, YearsActive +from ._types import YearsActive from ._version import Version, _get_version __version__ = _get_version() @@ -82,12 +57,6 @@ "MediaStatus", "MediaType", # Types - "AniListID", - "AniListTitle", - "AniListYear", - "Color", - "CountryCode", - "HttpUrl", "YearsActive", # Models "AiringSchedule", @@ -110,32 +79,6 @@ "StaffName", "Studio", # Exceptions - "CloseError", - "ConnectError", - "ConnectTimeout", - "CookieConflict", - "DecodingError", - "HTTPError", "HTTPStatusError", - "InvalidURL", - "LocalProtocolError", - "NetworkError", - "PoolTimeout", - "ProtocolError", - "ProxyError", - "ReadError", - "ReadTimeout", - "RemoteProtocolError", - "RequestError", - "RequestNotRead", - "ResponseNotRead", - "StreamClosed", - "StreamConsumed", - "StreamError", - "TimeoutException", - "TooManyRedirects", - "UnsupportedProtocol", - "WriteError", - "WriteTimeout", "ValidationError", ] diff --git a/src/pyanilist/_clients/__init__.py b/src/pyanilist/_clients/__init__.py index ce756d3..b9d4a57 100644 --- a/src/pyanilist/_clients/__init__.py +++ b/src/pyanilist/_clients/__init__.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from ._async import AsyncAniList from ._sync import AniList diff --git a/src/pyanilist/_clients/_async.py b/src/pyanilist/_clients/_async.py index dd5d824..bc8b6df 100644 --- a/src/pyanilist/_clients/_async.py +++ b/src/pyanilist/_clients/_async.py @@ -1,25 +1,26 @@ from __future__ import annotations +from collections.abc import Iterable from typing import Any -import httpx +from httpx import AsyncClient, HTTPError, Response from pydantic import PositiveInt, validate_call +from pydantic_extra_types.country import CountryAlpha2 as CountryCode from stamina import retry_context -from .._enums import MediaFormat, MediaSeason, MediaStatus, MediaType +from .._enums import MediaFormat, MediaSeason, MediaSort, MediaSource, MediaStatus, MediaType from .._models import Media +from .._parser import post_process_response from .._query import query_string -from .._types import AniListID, AniListTitle, AniListYear, HTTPXAsyncClientKwargs -from .._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter +from .._types import FuzzyDateInt +from .._utils import query_variables_constructor class AsyncAniList: @validate_call - def __init__( - self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: HTTPXAsyncClientKwargs - ) -> None: + def __init__(self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: Any) -> None: """ - Async AniList API client. + AniList API client. Parameters ---------- @@ -28,43 +29,22 @@ def __init__( retries : PositiveInt, optional Number of times to retry a failed request before raising an error. Default is 5. Set this to 1 to disable retrying. - kwargs : HTTPXAsyncClientKwargs, optional - Keyword arguments to pass to the underlying [httpx.AsyncClient()](https://www.python-httpx.org/api/#asyncclient) + kwargs : Any, optional + Keyword arguments to pass to the underlying [`httpx.AsyncClient`](https://www.python-httpx.org/api/#asyncclient) used to make the POST request. """ self.api_url = api_url self.retries = retries self.kwargs = kwargs - async def _post_request( - self, - id: AniListID | None = None, - season: MediaSeason | None = None, - season_year: AniListYear | None = None, - type: MediaType | None = None, - format: MediaFormat | None = None, - status: MediaStatus | None = None, - title: AniListTitle | None = None, - ) -> httpx.Response: + async def _post_request(self, **kwargs: Any) -> Response: """ Make a POST request to the AniList API. Parameters ---------- - id : AniListID, optional - AniList ID of the media as found in the URL: `https://anilist.co/{type}/{id}`. Default is None. - season : MediaSeason | None, optional - The season the media was initially released in. Default is None. - season_year : AniListYear | None, optional - The season year the media was initially released in. Default is None. - type : MediaType | None, optional - The type of the media; anime or manga. Default is None. - format : MediaFormat | None, optional - The format the media was released in. Default is None. - status : MediaStatus | None, optional - The current releasing status of the media. Default is None. - title : AniListTitle | None, optional - The string used for searching on AniList. Default is None. + kwargs : Any + Anilist query kwargs Raises ------ @@ -78,175 +58,233 @@ async def _post_request( The response object from the AniList API. """ - # map params with AniList's - query_variables = dict( - id=id, - season=season, - seasonYear=season_year, - type=type, - format=format, - status=status, - search=title, - ) - payload = { "query": query_string, - "variables": {key: value for key, value in query_variables.items() if value is not None}, + "variables": query_variables_constructor(kwargs), } - async for attempt in retry_context(on=httpx.HTTPError, attempts=self.retries): + async for attempt in retry_context(on=HTTPError, attempts=self.retries): with attempt: - async with httpx.AsyncClient(**self.kwargs) as client: + async with AsyncClient(**self.kwargs) as client: response = await client.post(self.api_url, json=payload) response.raise_for_status() return response - @staticmethod - async def _process_description(dictionary: dict[str, Any]) -> dict[str, Any]: - """ - Anilist's description field takes a parameter `asHtml: boolean`, effectively - resulting in two differently formatted descriptions. - - Despite what the name implies, `asHtml` being `False` does not gurantee that there will be no `HTML` - tags in the description. - - So we do a bit of post processing: - - Sanitize the resulting descriptions - - Introduce two more formats derived from the original two, i.e, markdown and plain text - - Nest our newly acquired 4 descriptions into a single parent dictionary - - Example: - - This - ```py - { - "defaultDescription": "...", - "htmlDescription": "...", - } - ``` - Turns into this: - ```py - { - "description": { - "default": "...", - "html": "...", - "markdown": "...", - "text": "...", - } - } - ```py - - """ - - default_description = sanitize_description(dictionary.get("defaultDescription")) - html_description = sanitize_description(dictionary.get("htmlDescription")) - markdown_description = markdown_formatter(html_description) - text_description = text_formatter(default_description) - - # Delete the processed keys - dictionary.pop("defaultDescription", None) - dictionary.pop("htmlDescription", None) - - # Nest them inside a parent dictionary - return dict( - default=default_description, - html=html_description, - markdown=markdown_description, - text=text_description, - ) - - async def _post_process_response(self, response: httpx.Response) -> dict[str, Any]: - """ - Post-processes the response from AniList API. - - Parameters - ---------- - response : Response - The response object received from AniList API. - - Returns - ------- - dict[str, Any] - Processed dictionary containing media information. - - Notes - ----- - Currently, this function does two things: - 1. Flattening nested structures such as relations, studios, characters, and staff. - 2. Removing null fields to ensure a cleaner output. - """ - - # type hinting for IDE because it doesn't detect it automagically - dictionary: dict[str, Any] - - dictionary = response.json()["data"]["Media"] - - # "Flatten" the nested list of dictionaries of list of dictionaries... blah blah - # into simpler list for more intuitive access - relations = dictionary.get("relations") - dictionary.pop("relations", None) - flattened_relations = flatten(relations, "relationType") - - # same thing here - studios = dictionary.get("studios") - dictionary.pop("studios", None) - flattened_studios = flatten(studios, "isMain") - - # same thing here - characters = dictionary.get("characters") - dictionary.pop("characters", None) - flattened_characters = flatten(characters, "role") - - # same thing here - staff = dictionary.get("staff") - dictionary.pop("staff", None) - flattened_staff = flatten(staff, "role") - - # Process description - dictionary["description"] = await self._process_description(dictionary) - - # Process description of every relation - for relation in flattened_relations: - relation["description"] = await self._process_description(relation) - - # replace the original - dictionary["relations"] = flattened_relations - dictionary["studios"] = flattened_studios - dictionary["characters"] = flattened_characters - dictionary["staff"] = flattened_staff - - # self explanatory, details on why - # are in the function docstring - return remove_null_fields(dictionary) - @validate_call - async def search( + async def get( self, - title: AniListTitle, + search: str | None = None, + *, + id: int | None = None, + id_mal: int | None = None, + start_date: FuzzyDateInt | None = None, + end_date: FuzzyDateInt | None = None, season: MediaSeason | None = None, - season_year: AniListYear | None = None, + season_year: int | None = None, type: MediaType | None = None, format: MediaFormat | None = None, status: MediaStatus | None = None, + episodes: int | None = None, + chapters: int | None = None, + duration: int | None = None, + volumes: int | None = None, + is_adult: bool | None = None, + genre: str | None = None, + tag: str | None = None, + minimum_tag_rank: int | None = None, + tag_category: str | None = None, + licensed_by: str | None = None, + licensed_by_id: int | None = None, + average_score: int | None = None, + popularity: int | None = None, + source: MediaSource | None = None, + country_of_origin: CountryCode | str | None = None, + is_licensed: bool | None = None, + id_not: int | None = None, + id_in: Iterable[int] | None = None, + id_not_in: Iterable[int] | None = None, + id_mal_not: int | None = None, + id_mal_in: Iterable[int] | None = None, + id_mal_not_in: Iterable[int] | None = None, + start_date_greater: FuzzyDateInt | None = None, + start_date_lesser: FuzzyDateInt | None = None, + start_date_like: str | None = None, + end_date_greater: FuzzyDateInt | None = None, + end_date_lesser: FuzzyDateInt | None = None, + end_date_like: str | None = None, + format_in: Iterable[MediaFormat] | None = None, + format_not: MediaFormat | None = None, + format_not_in: Iterable[MediaFormat] | None = None, + status_in: Iterable[MediaStatus] | None = None, + status_not: MediaStatus | None = None, + status_not_in: Iterable[MediaStatus] | None = None, + episodes_greater: int | None = None, + episodes_lesser: int | None = None, + duration_greater: int | None = None, + duration_lesser: int | None = None, + chapters_greater: int | None = None, + chapters_lesser: int | None = None, + volumes_greater: int | None = None, + volumes_lesser: int | None = None, + genre_in: Iterable[str] | None = None, + genre_not_in: Iterable[str] | None = None, + tag_in: Iterable[str] | None = None, + tag_not_in: Iterable[str] | None = None, + tag_category_in: Iterable[str] | None = None, + tag_category_not_in: Iterable[str] | None = None, + licensed_by_in: Iterable[str] | None = None, + licensed_by_id_in: Iterable[int] | None = None, + average_score_not: int | None = None, + average_score_greater: int | None = None, + average_score_lesser: int | None = None, + popularity_not: int | None = None, + popularity_greater: int | None = None, + popularity_lesser: int | None = None, + source_in: Iterable[MediaSource] | None = None, + sort: Iterable[MediaSort] | None = None, ) -> Media: """ Search for media on AniList based on the provided parameters. Parameters ---------- - title : AniListTitle - The string used for searching on AniList. - season : MediaSeason | None, optional - The season the media was initially released in. Default is None. - season_year : AniListYear | None, optional - The season year the media was initially released in. Default is None. - type : MediaType | None, optional - The type of the media; anime or manga. Default is None. - format : MediaFormat | None, optional - The format the media was released in. Default is None. - status : MediaStatus | None, optional - The current releasing status of the media. Default is None. + search : str, optional + Filter by search query + id : int, optional + Filter by the media id + id_mal : int, optional + Filter by the media's MyAnimeList id + start_date : FuzzyDateInt, optional + Filter by the start date of the media + end_date : FuzzyDateInt, optional + Filter by the end date of the media + season : MediaSeason, optional + Filter by the season the media was released in + season_year : int, optional + The year of the season (Winter 2017 would also include December 2016 releases). Requires season argument + type : MediaType, optional + Filter by the media's type + format : MediaFormat, optional + Filter by the media's format + status : MediaStatus, optional + Filter by the media's current release status + episodes : int, optional + Filter by amount of episodes the media has + chapters : int, optional + Filter by the media's episode length + duration : int, optional + Filter by the media's chapter count + volumes : int, optional + Filter by the media's volume count + is_adult : bool, optional + Filter by if the media's intended for 18+ adult audiences + genre : str, optional + Filter by the media's genres + tag : str, optional + Filter by the media's tags + minimum_tag_rank : int, optional + Only apply the tags filter argument to tags above this rank. Default: 18 + tag_category : str, optional + Filter by the media's tags with in a tag category + licensed_by : str, optional + Filter media by sites name with a online streaming or reading license + licensed_by_id : int, optional + Filter media by sites id with a online streaming or reading license + average_score : int, optional + Filter by the media's average score + popularity : int, optional + Filter by the number of users with this media on their list + source : MediaSource, optional + Filter by the source type of the media + country_of_origin : CountryCode | str, optional + Filter by the media's country of origin + is_licensed : bool, optional + If the media is officially licensed or a self-published doujin release + id_not : int, optional + Filter by the media id + id_in : Iterable[int], optional + Filter by the media id + id_not_in : Iterable[int], optional + Filter by the media id + id_mal_not : int, optional + Filter by the media's MyAnimeList id + id_mal_in : Iterable[int], optional + Filter by the media's MyAnimeList id + id_mal_not_in : Iterable[int], optional + Filter by the media's MyAnimeList id + start_date_greater : FuzzyDateInt, optional + Filter by the start date of the media + start_date_lesser : FuzzyDateInt, optional + Filter by the start date of the media + start_date_like : str, optional + Filter by the start date of the media + end_date_greater : FuzzyDateInt, optional + Filter by the end date of the media + end_date_lesser : FuzzyDateInt, optional + Filter by the end date of the media + end_date_like : str, optional + Filter by the end date of the media + format_in : Iterable[MediaFormat], optional + Filter by the media's format + format_not : MediaFormat, optional + Filter by the media's format + format_not_in : Iterable[MediaFormat], optional + Filter by the media's format + status_in : Iterable[MediaStatus], optional + Filter by the media's current release status + status_not : MediaStatus, optional + Filter by the media's current release status + status_not_in : Iterable[MediaStatus], optional + Filter by the media's current release status + episodes_greater : int, optional + Filter by amount of episodes the media has + episodes_lesser : int, optional + Filter by amount of episodes the media has + duration_greater : int, optional + Filter by the media's episode length + duration_lesser : int, optional + Filter by the media's episode length + chapters_greater : int, optional + Filter by the media's chapter count + chapters_lesser : int, optional + Filter by the media's chapter count + volumes_greater : int, optional + Filter by the media's volume count + volumes_lesser : int, optional + Filter by the media's volume count + genre_in : Iterable[str], optional + Filter by the media's genres + genre_not_in : Iterable[str], optional + Filter by the media's genres + tag_in : Iterable[str], optional + Filter by the media's tags + tag_not_in : Iterable[str], optional + Filter by the media's tags + tag_category_in : Iterable[str], optional + Filter by the media's tags with in a tag category + tag_category_not_in : Iterable[str], optional + Filter by the media's tags with in a tag category + licensed_by_in : Iterable[str], optional + Filter media by sites name with a online streaming or reading license + licensed_by_id_in : Iterable[int], optional + Filter media by sites id with a online streaming or reading license + average_score_not : int, optional + Filter by the media's average score + average_score_greater : int, optional + Filter by the media's average score + average_score_lesser : int, optional + Filter by the media's average score + popularity_not : int, optional + Filter by the number of users with this media on their list + popularity_greater : int, optional + Filter by the number of users with this media on their list + popularity_lesser : int, optional + Filter by the number of users with this media on their list + source_in : Iterable[MediaSource], optional + Filter by the source type of the media + sort : Iterable[MediaSort], optional + The order the results will be returned in Raises ------ @@ -262,45 +300,76 @@ async def search( """ return Media.model_validate( - await self._post_process_response( + post_process_response( await self._post_request( - title=title, + id=id, + id_mal=id_mal, + start_date=start_date, + end_date=end_date, season=season, season_year=season_year, type=type, format=format, status=status, - ) - ) - ) - - @validate_call - async def get(self, id: AniListID) -> Media: - """ - Retrieve media information from AniList based on it's ID. - - Parameters - ---------- - id : int - AniList ID of the media as found in the URL: `https://anilist.co/{type}/{id}`. - - Raises - ------ - ValidationError - Invalid input - HTTPStatusError - AniList returned a non 2xx response. - - Returns - ------- - Media - A Media object representing the retrieved media information. - """ - - return Media.model_validate( - await self._post_process_response( - await self._post_request( - id=id, + episodes=episodes, + chapters=chapters, + duration=duration, + volumes=volumes, + is_adult=is_adult, + genre=genre, + tag=tag, + minimum_tag_rank=minimum_tag_rank, + tag_category=tag_category, + licensed_by=licensed_by, + licensed_by_id=licensed_by_id, + average_score=average_score, + popularity=popularity, + source=source, + country_of_origin=country_of_origin, + is_licensed=is_licensed, + search=search, + id_not=id_not, + id_in=id_in, + id_not_in=id_not_in, + id_mal_not=id_mal_not, + id_mal_in=id_mal_in, + id_mal_not_in=id_mal_not_in, + start_date_greater=start_date_greater, + start_date_lesser=start_date_lesser, + start_date_like=start_date_like, + end_date_greater=end_date_greater, + end_date_lesser=end_date_lesser, + end_date_like=end_date_like, + format_in=format_in, + format_not=format_not, + format_not_in=format_not_in, + status_in=status_in, + status_not=status_not, + status_not_in=status_not_in, + episodes_greater=episodes_greater, + episodes_lesser=episodes_lesser, + duration_greater=duration_greater, + duration_lesser=duration_lesser, + chapters_greater=chapters_greater, + chapters_lesser=chapters_lesser, + volumes_greater=volumes_greater, + volumes_lesser=volumes_lesser, + genre_in=genre_in, + genre_not_in=genre_not_in, + tag_in=tag_in, + tag_not_in=tag_not_in, + tag_category_in=tag_category_in, + tag_category_not_in=tag_category_not_in, + licensed_by_in=licensed_by_in, + licensed_by_id_in=licensed_by_id_in, + average_score_not=average_score_not, + average_score_greater=average_score_greater, + average_score_lesser=average_score_lesser, + popularity_not=popularity_not, + popularity_greater=popularity_greater, + popularity_lesser=popularity_lesser, + source_in=source_in, + sort=sort, ) ) ) diff --git a/src/pyanilist/_clients/_sync.py b/src/pyanilist/_clients/_sync.py index 33b2560..05adeee 100644 --- a/src/pyanilist/_clients/_sync.py +++ b/src/pyanilist/_clients/_sync.py @@ -1,22 +1,25 @@ from __future__ import annotations +from collections.abc import Iterable from typing import Any -import httpx +from httpx import Client, HTTPError, Response from pydantic import PositiveInt, validate_call +from pydantic_extra_types.country import CountryAlpha2 as CountryCode from stamina import retry_context -from .._enums import MediaFormat, MediaSeason, MediaStatus, MediaType +from .._enums import MediaFormat, MediaSeason, MediaSort, MediaSource, MediaStatus, MediaType from .._models import Media +from .._parser import post_process_response from .._query import query_string -from .._types import AniListID, AniListTitle, AniListYear, HTTPXClientKwargs -from .._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter +from .._types import FuzzyDateInt +from .._utils import query_variables_constructor class AniList: @validate_call def __init__( - self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: HTTPXClientKwargs + self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: Any ) -> None: """ AniList API client. @@ -28,43 +31,22 @@ def __init__( retries : PositiveInt, optional Number of times to retry a failed request before raising an error. Default is 5. Set this to 1 to disable retrying. - kwargs : HTTPXClientKwargs, optional - Keyword arguments to pass to the underlying [httpx.Client()](https://www.python-httpx.org/api/#client) + kwargs : Any, optional + Keyword arguments to pass to the underlying [`httpx.Client`](https://www.python-httpx.org/api/#client) used to make the POST request. """ self.api_url = api_url self.retries = retries self.kwargs = kwargs - def _post_request( - self, - id: AniListID | None = None, - season: MediaSeason | None = None, - season_year: AniListYear | None = None, - type: MediaType | None = None, - format: MediaFormat | None = None, - status: MediaStatus | None = None, - title: AniListTitle | None = None, - ) -> httpx.Response: + def _post_request(self, **kwargs: Any) -> Response: """ Make a POST request to the AniList API. Parameters ---------- - id : AniListID, optional - AniList ID of the media as found in the URL: `https://anilist.co/{type}/{id}`. Default is None. - season : MediaSeason | None, optional - The season the media was initially released in. Default is None. - season_year : AniListYear | None, optional - The season year the media was initially released in. Default is None. - type : MediaType | None, optional - The type of the media; anime or manga. Default is None. - format : MediaFormat | None, optional - The format the media was released in. Default is None. - status : MediaStatus | None, optional - The current releasing status of the media. Default is None. - title : AniListTitle | None, optional - The string used for searching on AniList. Default is None. + kwargs : Any + Anilist query kwargs Raises ------ @@ -78,174 +60,232 @@ def _post_request( The response object from the AniList API. """ - # map params with AniList's - query_variables = dict( - id=id, - season=season, - seasonYear=season_year, - type=type, - format=format, - status=status, - search=title, - ) - payload = { "query": query_string, - "variables": {key: value for key, value in query_variables.items() if value is not None}, + "variables": query_variables_constructor(kwargs), } - for attempt in retry_context(on=httpx.HTTPError, attempts=self.retries): + for attempt in retry_context(on=HTTPError, attempts=self.retries): with attempt: - with httpx.Client(**self.kwargs) as client: + with Client(**self.kwargs) as client: response = client.post(self.api_url, json=payload).raise_for_status() - + return response - @staticmethod - def _process_description(dictionary: dict[str, Any]) -> dict[str, Any]: - """ - Anilist's description field takes a parameter `asHtml: boolean`, effectively - resulting in two differently formatted descriptions. - - Despite what the name implies, `asHtml` being `False` does not gurantee that there will be no `HTML` - tags in the description. - - So we do a bit of post processing: - - Sanitize the resulting descriptions - - Introduce two more formats derived from the original two, i.e, markdown and plain text - - Nest our newly acquired 4 descriptions into a single parent dictionary - - Example: - - This - ```py - { - "defaultDescription": "...", - "htmlDescription": "...", - } - ``` - Turns into this: - ```py - { - "description": { - "default": "...", - "html": "...", - "markdown": "...", - "text": "...", - } - } - ```py - - """ - - default_description = sanitize_description(dictionary.get("defaultDescription")) - html_description = sanitize_description(dictionary.get("htmlDescription")) - markdown_description = markdown_formatter(html_description) - text_description = text_formatter(default_description) - - # Delete the processed keys - dictionary.pop("defaultDescription", None) - dictionary.pop("htmlDescription", None) - - # Nest them inside a parent dictionary - return dict( - default=default_description, - html=html_description, - markdown=markdown_description, - text=text_description, - ) - - def _post_process_response(self, response: httpx.Response) -> dict[str, Any]: - """ - Post-processes the response from AniList API. - - Parameters - ---------- - response : Response - The response object received from AniList API. - - Returns - ------- - dict[str, Any] - Processed dictionary containing media information. - - Notes - ----- - Currently, this function does two things: - 1. Flattening nested structures such as relations, studios, characters, and staff. - 2. Removing null fields to ensure a cleaner output. - """ - - # type hinting for IDE because it doesn't detect it automagically - dictionary: dict[str, Any] - - dictionary = response.json()["data"]["Media"] - - # "Flatten" the nested list of dictionaries of list of dictionaries... blah blah - # into simpler list for more intuitive access - relations = dictionary.get("relations") - dictionary.pop("relations", None) - flattened_relations = flatten(relations, "relationType") - - # same thing here - studios = dictionary.get("studios") - dictionary.pop("studios", None) - flattened_studios = flatten(studios, "isMain") - - # same thing here - characters = dictionary.get("characters") - dictionary.pop("characters", None) - flattened_characters = flatten(characters, "role") - - # same thing here - staff = dictionary.get("staff") - dictionary.pop("staff", None) - flattened_staff = flatten(staff, "role") - - # Process description - dictionary["description"] = self._process_description(dictionary) - - # Process description of every relation - for relation in flattened_relations: - relation["description"] = self._process_description(relation) - - # replace the original - dictionary["relations"] = flattened_relations - dictionary["studios"] = flattened_studios - dictionary["characters"] = flattened_characters - dictionary["staff"] = flattened_staff - - # self explanatory, details on why - # are in the function docstring - return remove_null_fields(dictionary) - @validate_call - def search( + def get( self, - title: AniListTitle, + search: str | None = None, + *, + id: int | None = None, + id_mal: int | None = None, + start_date: FuzzyDateInt | None = None, + end_date: FuzzyDateInt | None = None, season: MediaSeason | None = None, - season_year: AniListYear | None = None, + season_year: int | None = None, type: MediaType | None = None, format: MediaFormat | None = None, status: MediaStatus | None = None, + episodes: int | None = None, + chapters: int | None = None, + duration: int | None = None, + volumes: int | None = None, + is_adult: bool | None = None, + genre: str | None = None, + tag: str | None = None, + minimum_tag_rank: int | None = None, + tag_category: str | None = None, + licensed_by: str | None = None, + licensed_by_id: int | None = None, + average_score: int | None = None, + popularity: int | None = None, + source: MediaSource | None = None, + country_of_origin: CountryCode | str | None = None, + is_licensed: bool | None = None, + id_not: int | None = None, + id_in: Iterable[int] | None = None, + id_not_in: Iterable[int] | None = None, + id_mal_not: int | None = None, + id_mal_in: Iterable[int] | None = None, + id_mal_not_in: Iterable[int] | None = None, + start_date_greater: FuzzyDateInt | None = None, + start_date_lesser: FuzzyDateInt | None = None, + start_date_like: str | None = None, + end_date_greater: FuzzyDateInt | None = None, + end_date_lesser: FuzzyDateInt | None = None, + end_date_like: str | None = None, + format_in: Iterable[MediaFormat] | None = None, + format_not: MediaFormat | None = None, + format_not_in: Iterable[MediaFormat] | None = None, + status_in: Iterable[MediaStatus] | None = None, + status_not: MediaStatus | None = None, + status_not_in: Iterable[MediaStatus] | None = None, + episodes_greater: int | None = None, + episodes_lesser: int | None = None, + duration_greater: int | None = None, + duration_lesser: int | None = None, + chapters_greater: int | None = None, + chapters_lesser: int | None = None, + volumes_greater: int | None = None, + volumes_lesser: int | None = None, + genre_in: Iterable[str] | None = None, + genre_not_in: Iterable[str] | None = None, + tag_in: Iterable[str] | None = None, + tag_not_in: Iterable[str] | None = None, + tag_category_in: Iterable[str] | None = None, + tag_category_not_in: Iterable[str] | None = None, + licensed_by_in: Iterable[str] | None = None, + licensed_by_id_in: Iterable[int] | None = None, + average_score_not: int | None = None, + average_score_greater: int | None = None, + average_score_lesser: int | None = None, + popularity_not: int | None = None, + popularity_greater: int | None = None, + popularity_lesser: int | None = None, + source_in: Iterable[MediaSource] | None = None, + sort: Iterable[MediaSort] | None = None, ) -> Media: """ Search for media on AniList based on the provided parameters. Parameters ---------- - title : AniListTitle - The string used for searching on AniList. - season : MediaSeason | None, optional - The season the media was initially released in. Default is None. - season_year : AniListYear | None, optional - The season year the media was initially released in. Default is None. - type : MediaType | None, optional - The type of the media; anime or manga. Default is None. - format : MediaFormat | None, optional - The format the media was released in. Default is None. - status : MediaStatus | None, optional - The current releasing status of the media. Default is None. + search : str, optional + Filter by search query + id : int, optional + Filter by the media id + id_mal : int, optional + Filter by the media's MyAnimeList id + start_date : FuzzyDateInt, optional + Filter by the start date of the media + end_date : FuzzyDateInt, optional + Filter by the end date of the media + season : MediaSeason, optional + Filter by the season the media was released in + season_year : int, optional + The year of the season (Winter 2017 would also include December 2016 releases). Requires season argument + type : MediaType, optional + Filter by the media's type + format : MediaFormat, optional + Filter by the media's format + status : MediaStatus, optional + Filter by the media's current release status + episodes : int, optional + Filter by amount of episodes the media has + chapters : int, optional + Filter by the media's episode length + duration : int, optional + Filter by the media's chapter count + volumes : int, optional + Filter by the media's volume count + is_adult : bool, optional + Filter by if the media's intended for 18+ adult audiences + genre : str, optional + Filter by the media's genres + tag : str, optional + Filter by the media's tags + minimum_tag_rank : int, optional + Only apply the tags filter argument to tags above this rank. Default: 18 + tag_category : str, optional + Filter by the media's tags with in a tag category + licensed_by : str, optional + Filter media by sites name with a online streaming or reading license + licensed_by_id : int, optional + Filter media by sites id with a online streaming or reading license + average_score : int, optional + Filter by the media's average score + popularity : int, optional + Filter by the number of users with this media on their list + source : MediaSource, optional + Filter by the source type of the media + country_of_origin : CountryCode | str, optional + Filter by the media's country of origin + is_licensed : bool, optional + If the media is officially licensed or a self-published doujin release + id_not : int, optional + Filter by the media id + id_in : Iterable[int], optional + Filter by the media id + id_not_in : Iterable[int], optional + Filter by the media id + id_mal_not : int, optional + Filter by the media's MyAnimeList id + id_mal_in : Iterable[int], optional + Filter by the media's MyAnimeList id + id_mal_not_in : Iterable[int], optional + Filter by the media's MyAnimeList id + start_date_greater : FuzzyDateInt, optional + Filter by the start date of the media + start_date_lesser : FuzzyDateInt, optional + Filter by the start date of the media + start_date_like : str, optional + Filter by the start date of the media + end_date_greater : FuzzyDateInt, optional + Filter by the end date of the media + end_date_lesser : FuzzyDateInt, optional + Filter by the end date of the media + end_date_like : str, optional + Filter by the end date of the media + format_in : Iterable[MediaFormat], optional + Filter by the media's format + format_not : MediaFormat, optional + Filter by the media's format + format_not_in : Iterable[MediaFormat], optional + Filter by the media's format + status_in : Iterable[MediaStatus], optional + Filter by the media's current release status + status_not : MediaStatus, optional + Filter by the media's current release status + status_not_in : Iterable[MediaStatus], optional + Filter by the media's current release status + episodes_greater : int, optional + Filter by amount of episodes the media has + episodes_lesser : int, optional + Filter by amount of episodes the media has + duration_greater : int, optional + Filter by the media's episode length + duration_lesser : int, optional + Filter by the media's episode length + chapters_greater : int, optional + Filter by the media's chapter count + chapters_lesser : int, optional + Filter by the media's chapter count + volumes_greater : int, optional + Filter by the media's volume count + volumes_lesser : int, optional + Filter by the media's volume count + genre_in : Iterable[str], optional + Filter by the media's genres + genre_not_in : Iterable[str], optional + Filter by the media's genres + tag_in : Iterable[str], optional + Filter by the media's tags + tag_not_in : Iterable[str], optional + Filter by the media's tags + tag_category_in : Iterable[str], optional + Filter by the media's tags with in a tag category + tag_category_not_in : Iterable[str], optional + Filter by the media's tags with in a tag category + licensed_by_in : Iterable[str], optional + Filter media by sites name with a online streaming or reading license + licensed_by_id_in : Iterable[int], optional + Filter media by sites id with a online streaming or reading license + average_score_not : int, optional + Filter by the media's average score + average_score_greater : int, optional + Filter by the media's average score + average_score_lesser : int, optional + Filter by the media's average score + popularity_not : int, optional + Filter by the number of users with this media on their list + popularity_greater : int, optional + Filter by the number of users with this media on their list + popularity_lesser : int, optional + Filter by the number of users with this media on their list + source_in : Iterable[MediaSource], optional + Filter by the source type of the media + sort : Iterable[MediaSort], optional + The order the results will be returned in Raises ------ @@ -261,45 +301,76 @@ def search( """ return Media.model_validate( - self._post_process_response( + post_process_response( self._post_request( - title=title, + id=id, + id_mal=id_mal, + start_date=start_date, + end_date=end_date, season=season, season_year=season_year, type=type, format=format, status=status, - ) - ) - ) - - @validate_call - def get(self, id: AniListID) -> Media: - """ - Retrieve media information from AniList based on it's ID. - - Parameters - ---------- - id : int - AniList ID of the media as found in the URL: `https://anilist.co/{type}/{id}`. - - Raises - ------ - ValidationError - Invalid input - HTTPStatusError - AniList returned a non 2xx response. - - Returns - ------- - Media - A Media object representing the retrieved media information. - """ - - return Media.model_validate( - self._post_process_response( - self._post_request( - id=id, + episodes=episodes, + chapters=chapters, + duration=duration, + volumes=volumes, + is_adult=is_adult, + genre=genre, + tag=tag, + minimum_tag_rank=minimum_tag_rank, + tag_category=tag_category, + licensed_by=licensed_by, + licensed_by_id=licensed_by_id, + average_score=average_score, + popularity=popularity, + source=source, + country_of_origin=country_of_origin, + is_licensed=is_licensed, + search=search, + id_not=id_not, + id_in=id_in, + id_not_in=id_not_in, + id_mal_not=id_mal_not, + id_mal_in=id_mal_in, + id_mal_not_in=id_mal_not_in, + start_date_greater=start_date_greater, + start_date_lesser=start_date_lesser, + start_date_like=start_date_like, + end_date_greater=end_date_greater, + end_date_lesser=end_date_lesser, + end_date_like=end_date_like, + format_in=format_in, + format_not=format_not, + format_not_in=format_not_in, + status_in=status_in, + status_not=status_not, + status_not_in=status_not_in, + episodes_greater=episodes_greater, + episodes_lesser=episodes_lesser, + duration_greater=duration_greater, + duration_lesser=duration_lesser, + chapters_greater=chapters_greater, + chapters_lesser=chapters_lesser, + volumes_greater=volumes_greater, + volumes_lesser=volumes_lesser, + genre_in=genre_in, + genre_not_in=genre_not_in, + tag_in=tag_in, + tag_not_in=tag_not_in, + tag_category_in=tag_category_in, + tag_category_not_in=tag_category_not_in, + licensed_by_in=licensed_by_in, + licensed_by_id_in=licensed_by_id_in, + average_score_not=average_score_not, + average_score_greater=average_score_greater, + average_score_lesser=average_score_lesser, + popularity_not=popularity_not, + popularity_greater=popularity_greater, + popularity_lesser=popularity_lesser, + source_in=source_in, + sort=sort, ) ) ) diff --git a/src/pyanilist/_compat.py b/src/pyanilist/_compat.py index 018be54..6365446 100644 --- a/src/pyanilist/_compat.py +++ b/src/pyanilist/_compat.py @@ -1,4 +1,5 @@ """Compatibility module to for older python versions""" +from __future__ import annotations import sys diff --git a/src/pyanilist/_enums.py b/src/pyanilist/_enums.py index 127be97..8f81061 100644 --- a/src/pyanilist/_enums.py +++ b/src/pyanilist/_enums.py @@ -1,3 +1,5 @@ +from __future__ import annotations + from ._compat import StrEnum @@ -15,6 +17,8 @@ def title(self) -> str: # type: ignore "TV_SHORT": "TV Short", "OVA": "OVA", "ONA": "ONA", + "ID": "ID", + "ID_DESC": "ID Desc", } if self.value in exceptions: @@ -237,6 +241,48 @@ class MediaRankType(BaseStrEnum): """Ranking is based on the media's popularity""" +class MediaSort(BaseStrEnum): + """Media sort enums""" + + ID = "ID" + ID_DESC = "ID_DESC" + TITLE_ROMAJI = "TITLE_ROMAJI" + TITLE_ROMAJI_DESC = "TITLE_ROMAJI_DESC" + TITLE_ENGLISH = "TITLE_ENGLISH" + TITLE_ENGLISH_DESC = "TITLE_ENGLISH_DESC" + TITLE_NATIVE = "TITLE_NATIVE" + TITLE_NATIVE_DESC = "TITLE_NATIVE_DESC" + TYPE = "TYPE" + TYPE_DESC = "TYPE_DESC" + FORMAT = "FORMAT" + FORMAT_DESC = "FORMAT_DESC" + START_DATE = "START_DATE" + START_DATE_DESC = "START_DATE_DESC" + END_DATE = "END_DATE" + END_DATE_DESC = "END_DATE_DESC" + SCORE = "SCORE" + SCORE_DESC = "SCORE_DESC" + POPULARITY = "POPULARITY" + POPULARITY_DESC = "POPULARITY_DESC" + TRENDING = "TRENDING" + TRENDING_DESC = "TRENDING_DESC" + EPISODES = "EPISODES" + EPISODES_DESC = "EPISODES_DESC" + DURATION = "DURATION" + DURATION_DESC = "DURATION_DESC" + STATUS = "STATUS" + STATUS_DESC = "STATUS_DESC" + CHAPTERS = "CHAPTERS" + CHAPTERS_DESC = "CHAPTERS_DESC" + VOLUMES = "VOLUMES" + VOLUMES_DESC = "VOLUMES_DESC" + UPDATED_AT = "UPDATED_AT" + UPDATED_AT_DESC = "UPDATED_AT_DESC" + SEARCH_MATCH = "SEARCH_MATCH" + FAVOURITES = "FAVOURITES" + FAVOURITES_DESC = "FAVOURITES_DESC" + + __all__ = [ "CharacterRole", "ExternalLinkType", @@ -244,6 +290,7 @@ class MediaRankType(BaseStrEnum): "MediaRankType", "MediaRelation", "MediaSeason", + "MediaSort", "MediaSource", "MediaStatus", "MediaType", diff --git a/src/pyanilist/_exceptions.py b/src/pyanilist/_exceptions.py deleted file mode 100644 index 2a29f2f..0000000 --- a/src/pyanilist/_exceptions.py +++ /dev/null @@ -1,67 +0,0 @@ -""" -This module simply re-exports Exceptions from -[`httpx`](https://www.python-httpx.org/exceptions/) and -[`pydantic`](https://docs.pydantic.dev/latest/api/pydantic_core/#pydantic_core.ValidationError) for convenience. -""" - -from httpx import ( - CloseError, - ConnectError, - ConnectTimeout, - CookieConflict, - DecodingError, - HTTPError, - HTTPStatusError, - InvalidURL, - LocalProtocolError, - NetworkError, - PoolTimeout, - ProtocolError, - ProxyError, - ReadError, - ReadTimeout, - RemoteProtocolError, - RequestError, - RequestNotRead, - ResponseNotRead, - StreamClosed, - StreamConsumed, - StreamError, - TimeoutException, - TooManyRedirects, - UnsupportedProtocol, - WriteError, - WriteTimeout, -) -from pydantic import ValidationError - -__all__ = [ - "CloseError", - "ConnectError", - "ConnectTimeout", - "CookieConflict", - "DecodingError", - "HTTPError", - "HTTPStatusError", - "InvalidURL", - "LocalProtocolError", - "NetworkError", - "PoolTimeout", - "ProtocolError", - "ProxyError", - "ReadError", - "ReadTimeout", - "RemoteProtocolError", - "RequestError", - "RequestNotRead", - "ResponseNotRead", - "StreamClosed", - "StreamConsumed", - "StreamError", - "TimeoutException", - "TooManyRedirects", - "UnsupportedProtocol", - "WriteError", - "WriteTimeout", - "ValidationError", -] diff --git a/src/pyanilist/_models.py b/src/pyanilist/_models.py index 4f1b0aa..94a0d84 100644 --- a/src/pyanilist/_models.py +++ b/src/pyanilist/_models.py @@ -2,8 +2,10 @@ from datetime import datetime -from pydantic import AliasGenerator, BaseModel, ConfigDict +from pydantic import AliasGenerator, BaseModel, ConfigDict, HttpUrl from pydantic.alias_generators import to_camel +from pydantic_extra_types.color import Color +from pydantic_extra_types.country import CountryAlpha2 as CountryCode from ._enums import ( CharacterRole, @@ -16,7 +18,7 @@ MediaStatus, MediaType, ) -from ._types import Color, CountryCode, HttpUrl, YearsActive +from ._types import FuzzyDateInt, YearsActive class ParentModel(BaseModel): @@ -80,6 +82,20 @@ def iso_format(self) -> str: else: return "" + + def as_int(self) -> FuzzyDateInt: + """ + Return an 8 digit long date integer (YYYYMMDD). + Unknown dates represented by 0. + For example, 2016 is 20160000 and May 1976 is 19760500 + + The result is equivalent to AniList's FuzzyDateInt type. + """ + year = str(self.year).zfill(4) if self.year is not None else "1000" + month = str(self.month).zfill(2) if self.month is not None else "00" + day = str(self.day).zfill(2) if self.day is not None else "00" + + return int(f"{year}{month}{day}") class MediaTrailer(ParentModel): diff --git a/src/pyanilist/_parser.py b/src/pyanilist/_parser.py new file mode 100644 index 0000000..dbe1ec1 --- /dev/null +++ b/src/pyanilist/_parser.py @@ -0,0 +1,125 @@ +from __future__ import annotations + +from typing import TYPE_CHECKING, Any + +from ._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter + +if TYPE_CHECKING: + from httpx import Response + +def process_description(dictionary: dict[str, Any]) -> dict[str, Any]: + """ + Anilist's description field takes a parameter `asHtml: boolean`, effectively + resulting in two differently formatted descriptions. + + Despite what the name implies, `asHtml` being `False` does not gurantee that there will be no `HTML` + tags in the description. + + So we do a bit of post processing: + - Sanitize the resulting descriptions + - Introduce two more formats derived from the original two, i.e, markdown and plain text + - Nest our newly acquired 4 descriptions into a single parent dictionary + + Example: + + This + ```py + { + "defaultDescription": "...", + "htmlDescription": "...", + } + ``` + Turns into this: + ```py + { + "description": { + "default": "...", + "html": "...", + "markdown": "...", + "text": "...", + } + } + ```py + + """ + + default_description = sanitize_description(dictionary.get("defaultDescription")) + html_description = sanitize_description(dictionary.get("htmlDescription")) + markdown_description = markdown_formatter(html_description) + text_description = text_formatter(default_description) + + # Delete the processed keys + dictionary.pop("defaultDescription", None) + dictionary.pop("htmlDescription", None) + + # Nest them inside a parent dictionary + return dict( + default=default_description, + html=html_description, + markdown=markdown_description, + text=text_description, + ) + +def post_process_response(response: Response) -> dict[str, Any]: + """ + Post-processes the response from AniList API. + + Parameters + ---------- + response : Response + The response object received from AniList API. + + Returns + ------- + dict[str, Any] + Processed dictionary containing media information. + + Notes + ----- + Currently, this function does two things: + 1. Flattening nested structures such as relations, studios, characters, and staff. + 2. Removing null fields to ensure a cleaner output. + """ + + # type hinting for IDE because it doesn't detect it automagically + dictionary: dict[str, Any] + + dictionary = response.json()["data"]["Media"] + + # "Flatten" the nested list of dictionaries of list of dictionaries... blah blah + # into simpler list for more intuitive access + relations = dictionary.get("relations") + dictionary.pop("relations", None) + flattened_relations = flatten(relations, "relationType") + + # same thing here + studios = dictionary.get("studios") + dictionary.pop("studios", None) + flattened_studios = flatten(studios, "isMain") + + # same thing here + characters = dictionary.get("characters") + dictionary.pop("characters", None) + flattened_characters = flatten(characters, "role") + + # same thing here + staff = dictionary.get("staff") + dictionary.pop("staff", None) + flattened_staff = flatten(staff, "role") + + # Process description + dictionary["description"] = process_description(dictionary) + + # Process description of every relation + for relation in flattened_relations: + relation["description"] = process_description(relation) + + # replace the original + dictionary["relations"] = flattened_relations + dictionary["studios"] = flattened_studios + dictionary["characters"] = flattened_characters + dictionary["staff"] = flattened_staff + + # self explanatory, details on why + # are in the function docstring + return remove_null_fields(dictionary) \ No newline at end of file diff --git a/src/pyanilist/_query.py b/src/pyanilist/_query.py index e95595b..cc21b8c 100644 --- a/src/pyanilist/_query.py +++ b/src/pyanilist/_query.py @@ -1,6 +1,146 @@ query_string = """ -query ($id: Int, $season: MediaSeason, $seasonYear: Int, $type: MediaType, $format: MediaFormat, $status: MediaStatus, $search: String) { - Media(id: $id, season: $season, seasonYear: $seasonYear, type: $type, format: $format, status: $status, search: $search) { +query ( + $id: Int + $idMal: Int + $startDate: FuzzyDateInt + $endDate: FuzzyDateInt + $season: MediaSeason + $seasonYear: Int + $type: MediaType + $format: MediaFormat + $status: MediaStatus + $episodes: Int + $chapters: Int + $duration: Int + $volumes: Int + $isAdult: Boolean + $genre: String + $tag: String + $minimumTagRank: Int + $tagCategory: String + # $onList: Boolean + $licensedBy: String + $licensedById: Int + $averageScore: Int + $popularity: Int + $source: MediaSource + $countryOfOrigin: CountryCode + $isLicensed: Boolean + $search: String + $id_not: Int + $id_in: [Int] + $id_not_in: [Int] + $idMal_not: Int + $idMal_in: [Int] + $idMal_not_in: [Int] + $startDate_greater: FuzzyDateInt + $startDate_lesser: FuzzyDateInt + $startDate_like: String + $endDate_greater: FuzzyDateInt + $endDate_lesser: FuzzyDateInt + $endDate_like: String + $format_in: [MediaFormat] + $format_not: MediaFormat + $format_not_in: [MediaFormat] + $status_in: [MediaStatus] + $status_not: MediaStatus + $status_not_in: [MediaStatus] + $episodes_greater: Int + $episodes_lesser: Int + $duration_greater: Int + $duration_lesser: Int + $chapters_greater: Int + $chapters_lesser: Int + $volumes_greater: Int + $volumes_lesser: Int + $genre_in: [String] + $genre_not_in: [String] + $tag_in: [String] + $tag_not_in: [String] + $tagCategory_in: [String] + $tagCategory_not_in: [String] + $licensedBy_in: [String] + $licensedById_in: [Int] + $averageScore_not: Int + $averageScore_greater: Int + $averageScore_lesser: Int + $popularity_not: Int + $popularity_greater: Int + $popularity_lesser: Int + $source_in: [MediaSource] + $sort: [MediaSort] +) { + Media( + id: $id + idMal: $idMal + startDate: $startDate + endDate: $endDate + season: $season + seasonYear: $seasonYear + type: $type + format: $format + status: $status + episodes: $episodes + chapters: $chapters + duration: $duration + volumes: $volumes + isAdult: $isAdult + genre: $genre + tag: $tag + minimumTagRank: $minimumTagRank + tagCategory: $tagCategory + # $onList: $onList + licensedBy: $licensedBy + licensedById: $licensedById + averageScore: $averageScore + popularity: $popularity + source: $source + countryOfOrigin: $countryOfOrigin + isLicensed: $isLicensed + search: $search + id_not: $id_not + id_in: $id_in + id_not_in: $id_not_in + idMal_not: $idMal_not + idMal_in: $idMal_in + idMal_not_in: $idMal_not_in + startDate_greater: $startDate_greater + startDate_lesser: $startDate_lesser + startDate_like: $startDate_like + endDate_greater: $endDate_greater + endDate_lesser: $endDate_lesser + endDate_like: $endDate_like + format_in: $format_in + format_not: $format_not + format_not_in: $format_not_in + status_in: $status_in + status_not: $status_not + status_not_in: $status_not_in + episodes_greater: $episodes_greater + episodes_lesser: $episodes_lesser + duration_greater: $duration_greater + duration_lesser: $duration_lesser + chapters_greater: $chapters_greater + chapters_lesser: $chapters_lesser + volumes_greater: $volumes_greater + volumes_lesser: $volumes_lesser + genre_in: $genre_in + genre_not_in: $genre_not_in + tag_in: $tag_in + tag_not_in: $tag_not_in + tagCategory_in: $tagCategory_in + tagCategory_not_in: $tagCategory_not_in + licensedBy_in: $licensedBy_in + licensedById_in: $licensedById_in + averageScore_not: $averageScore_not + averageScore_greater: $averageScore_greater + averageScore_lesser: $averageScore_lesser + popularity_not: $popularity_not + popularity_greater: $popularity_greater + popularity_lesser: $popularity_lesser + source_in: $source_in + sort: $sort + ) { id idMal title { @@ -287,5 +427,4 @@ siteUrl } } - """ diff --git a/src/pyanilist/_types.py b/src/pyanilist/_types.py index bbf2402..e627b28 100644 --- a/src/pyanilist/_types.py +++ b/src/pyanilist/_types.py @@ -7,12 +7,10 @@ from __future__ import annotations -from typing import Annotated, Any +from typing import Annotated -from pydantic import Field, HttpUrl -from pydantic_extra_types.color import Color -from pydantic_extra_types.country import CountryAlpha2 as CountryCode -from typing_extensions import NamedTuple, TypeAlias +from pydantic import Field +from typing_extensions import NamedTuple class YearsActive(NamedTuple): @@ -25,22 +23,16 @@ class YearsActive(NamedTuple): end_year: int | None = None -AniListID = Annotated[int, Field(gt=0, description="AniList ID as found in the URL: https://anilist.co/{type}/{id}")] -AniListYear = Annotated[int, Field(ge=1000, description="Release Year")] -AniListTitle = Annotated[str, Field(min_length=1, description="Title of the media")] - -HTTPXClientKwargs: TypeAlias = Any -"""Simple TypeAlias to refer to `httpx.Client()` kwargs""" +FuzzyDateInt = Annotated[ + int, + Field( + ge=10000000, + le=99999999, + description="8 digit long date integer (YYYYMMDD). Unknown dates represented by 0. E.g. 2016: 20160000, May 1976: 19760500", + ), +] -HTTPXAsyncClientKwargs: TypeAlias = Any -"""Simple TypeAlias to refer to `httpx.AsyncClient()` kwargs""" __all__ = [ - "AniListID", - "AniListTitle", - "AniListYear", - "Color", - "CountryCode", - "HttpUrl", "YearsActive", ] diff --git a/src/pyanilist/_utils.py b/src/pyanilist/_utils.py index 4881e5d..b61080d 100644 --- a/src/pyanilist/_utils.py +++ b/src/pyanilist/_utils.py @@ -1,6 +1,7 @@ from __future__ import annotations import re +from collections.abc import Iterable from typing import Any import nh3 @@ -99,3 +100,90 @@ def remove_null_fields(dictionary: dict[str, Any]) -> dict[str, Any]: `None`, empty list, or empty dictionary. """ return remap(dictionary, lambda path, key, value: value not in [None, {}, []]) # type: ignore + +def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: + """ + Anilist doesn't stick to a single casing. + Most of it is camelCase but then there's some made up stuff in there too. + So can do nothing but create a mapping from snake_case to anilistCase + """ + casing = { + "id": "id", + "id_mal": "idMal", + "start_date": "startDate", + "end_date": "endDate", + "season": "season", + "season_year": "seasonYear", + "type": "type", + "format": "format", + "status": "status", + "episodes": "episodes", + "chapters": "chapters", + "duration": "duration", + "volumes": "volumes", + "is_adult": "isAdult", + "genre": "genre", + "tag": "tag", + "minimum_tag_rank": "minimumTagRank", + "tag_category": "tagCategory", + "licensed_by": "licensedBy", + "licensed_by_id": "licensedById", + "average_score": "averageScore", + "popularity": "popularity", + "source": "source", + "country_of_origin": "countryOfOrigin", + "is_licensed": "isLicensed", + "search": "search", + "id_not": "id_not", + "id_in": "id_in", + "id_not_in": "id_not_in", + "id_mal_not": "idMal_not", + "id_mal_in": "idMal_in", + "id_mal_not_in": "idMal_not_in", + "start_date_greater": "startDate_greater", + "start_date_lesser": "startDate_lesser", + "start_date_like": "startDate_like", + "end_date_greater": "endDate_greater", + "end_date_lesser": "endDate_lesser", + "end_date_like": "endDate_like", + "format_in": "format_in", + "format_not": "format_not", + "format_not_in": "format_not_in", + "status_in": "status_in", + "status_not": "status_not", + "status_not_in": "status_not_in", + "episodes_greater": "episodes_greater", + "episodes_lesser": "episodes_lesser", + "duration_greater": "duration_greater", + "duration_lesser": "duration_lesser", + "chapters_greater": "chapters_greater", + "chapters_lesser": "chapters_lesser", + "volumes_greater": "volumes_greater", + "volumes_lesser": "volumes_lesser", + "genre_in": "genre_in", + "genre_not_in": "genre_not_in", + "tag_in": "tag_in", + "tag_not_in": "tag_not_in", + "tag_category_in": "tagCategory_in", + "tag_category_not_in": "tagCategory_not_in", + "licensed_by_in": "licensedBy_in", + "licensed_by_id_in": "licensedById_in", + "average_score_not": "averageScore_not", + "average_score_greater": "averageScore_greater", + "average_score_lesser": "averageScore_lesser", + "popularity_not": "popularity_not", + "popularity_greater": "popularity_greater", + "popularity_lesser": "popularity_lesser", + "source_in": "source_in", + "sort": "sort", + } + + query_vars = {} + + for key, value in vars.items(): + if value is not None: + if isinstance(value, Iterable) and not isinstance(value, str): + value = tuple(value) + query_vars[casing[key]] = value + + return query_vars \ No newline at end of file diff --git a/src/pyanilist/_version.py b/src/pyanilist/_version.py index c44892e..2fefceb 100644 --- a/src/pyanilist/_version.py +++ b/src/pyanilist/_version.py @@ -1,22 +1,18 @@ +from __future__ import annotations + from typing_extensions import NamedTuple from ._compat import metadata class Version(NamedTuple): - """Version tuple based on SemVer""" - major: int - """Major version number""" minor: int - """Minor version number""" - patch: int - """Patch version number""" - + micro: int def _get_version() -> str: """ - Get the version of juicenet + Get the version of pyanilist """ try: return metadata.version("pyanilist") diff --git a/tests/test_anilist.py b/tests/test_anilist.py index 5593c24..10ded63 100644 --- a/tests/test_anilist.py +++ b/tests/test_anilist.py @@ -1,7 +1,6 @@ from pyanilist import ( AniList, CharacterRole, - HttpUrl, MediaFormat, MediaSeason, MediaSource, @@ -13,7 +12,7 @@ def test_anilist_anime() -> None: - media = AniList().search("Attack on titan", type=MediaType.ANIME) + media = AniList().get("Attack on titan", type=MediaType.ANIME) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2013 assert media.start_date.iso_format() == "2013-04-07" @@ -47,11 +46,11 @@ def test_anilist_anime() -> None: ("Daizen Komatsuda", "Storyboard (ep 23)"), ("You Moriyama", "Key Animation (OP1)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/16498") + assert media.site_url.__str__() == "https://anilist.co/anime/16498" def test_anilist_manga() -> None: - media = AniList().search("Attack on titan", type=MediaType.MANGA) + media = AniList().get("Attack on titan", type=MediaType.MANGA) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2009 assert media.start_date.iso_format() == "2009-09-09" @@ -73,11 +72,11 @@ def test_anilist_manga() -> None: ("Shintarou Kawakubo", "Editing"), ("Yifeng Zhang", "Translator (Chinese)"), ] - assert media.site_url == HttpUrl("https://anilist.co/manga/53390") + assert media.site_url.__str__() == "https://anilist.co/manga/53390" def test_anilist_with_some_constraints() -> None: - media = AniList().search( + media = AniList().get( "violet evergarden", type=MediaType.MANGA, format=MediaFormat.NOVEL, status=MediaStatus.FINISHED ) assert media.title.romaji == "Violet Evergarden" @@ -90,11 +89,11 @@ def test_anilist_with_some_constraints() -> None: ("Akiko Takase", "Illustration"), ("Kana Akatsuki", "Story"), ] - assert media.site_url == HttpUrl("https://anilist.co/manga/97298") + assert media.site_url.__str__() == "https://anilist.co/manga/97298" def test_anilist_with_all_constraints() -> None: - media = AniList().search( + media = AniList().get( "My Hero Academia", season=MediaSeason.SPRING, season_year=2016, @@ -135,11 +134,11 @@ def test_anilist_with_all_constraints() -> None: ("Katsuyuki Kodera", "Storyboard (eps 5, 9, 13)"), ("Kenji Nagasaki", "Storyboard (OP, ED, eps 1, 2)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/21459") + assert media.site_url.__str__() =="https://anilist.co/anime/21459" def test_anilist_id() -> None: - media = AniList().get(16498) + media = AniList().get(id=16498) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2013 assert media.source is MediaSource.MANGA @@ -173,11 +172,11 @@ def test_anilist_id() -> None: ("Daizen Komatsuda", "Storyboard (ep 23)"), ("You Moriyama", "Key Animation (OP1)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/16498") + assert media.site_url.__str__() == "https://anilist.co/anime/16498" def test_anilist_description() -> None: - media = AniList().get(106794) + media = AniList().get(id=106794) assert media.title.english == "Bloom Into You Anthology" assert media.start_date.year == 2018 assert media.source is MediaSource.MANGA @@ -190,11 +189,11 @@ def test_anilist_description() -> None: assert media.relations[0].description.html == BloomIntoYouDescriptions.HTML assert media.relations[0].description.markdown == BloomIntoYouDescriptions.MARKDOWN assert media.relations[0].description.text == BloomIntoYouDescriptions.TEXT - assert media.site_url == HttpUrl("https://anilist.co/manga/106794") + assert media.site_url.__str__() == "https://anilist.co/manga/106794" def test_anilist_characters() -> None: - media = AniList().get(20954) + media = AniList().get(id=20954) assert media.title.english == "A Silent Voice" assert media.start_date.year == 2016 assert media.source is MediaSource.MANGA @@ -203,4 +202,4 @@ def test_anilist_characters() -> None: "Shouya Ishida", "Shouko Nishimiya", ] - assert media.site_url == HttpUrl("https://anilist.co/anime/20954") + assert media.site_url.__str__() == "https://anilist.co/anime/20954" diff --git a/tests/test_async_anilist.py b/tests/test_async_anilist.py index 0724fcd..f5ecae0 100644 --- a/tests/test_async_anilist.py +++ b/tests/test_async_anilist.py @@ -1,7 +1,6 @@ from pyanilist import ( AsyncAniList, CharacterRole, - HttpUrl, MediaFormat, MediaSeason, MediaSource, @@ -13,7 +12,7 @@ async def test_anilist_anime() -> None: - media = await AsyncAniList().search("Attack on titan", type=MediaType.ANIME) + media = await AsyncAniList().get("Attack on titan", type=MediaType.ANIME) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2013 assert media.start_date.iso_format() == "2013-04-07" @@ -47,11 +46,11 @@ async def test_anilist_anime() -> None: ("Daizen Komatsuda", "Storyboard (ep 23)"), ("You Moriyama", "Key Animation (OP1)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/16498") + assert media.site_url.__str__() == "https://anilist.co/anime/16498" async def test_anilist_manga() -> None: - media = await AsyncAniList().search("Attack on titan", type=MediaType.MANGA) + media = await AsyncAniList().get("Attack on titan", type=MediaType.MANGA) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2009 assert media.start_date.iso_format() == "2009-09-09" @@ -73,11 +72,11 @@ async def test_anilist_manga() -> None: ("Shintarou Kawakubo", "Editing"), ("Yifeng Zhang", "Translator (Chinese)"), ] - assert media.site_url == HttpUrl("https://anilist.co/manga/53390") + assert media.site_url.__str__() == "https://anilist.co/manga/53390" async def test_anilist_with_some_constraints() -> None: - media = await AsyncAniList().search( + media = await AsyncAniList().get( "violet evergarden", type=MediaType.MANGA, format=MediaFormat.NOVEL, status=MediaStatus.FINISHED ) assert media.title.romaji == "Violet Evergarden" @@ -90,11 +89,11 @@ async def test_anilist_with_some_constraints() -> None: ("Akiko Takase", "Illustration"), ("Kana Akatsuki", "Story"), ] - assert media.site_url == HttpUrl("https://anilist.co/manga/97298") + assert media.site_url.__str__() == "https://anilist.co/manga/97298" async def test_anilist_with_all_constraints() -> None: - media = await AsyncAniList().search( + media = await AsyncAniList().get( "My Hero Academia", season=MediaSeason.SPRING, season_year=2016, @@ -135,11 +134,11 @@ async def test_anilist_with_all_constraints() -> None: ("Katsuyuki Kodera", "Storyboard (eps 5, 9, 13)"), ("Kenji Nagasaki", "Storyboard (OP, ED, eps 1, 2)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/21459") + assert media.site_url.__str__() == "https://anilist.co/anime/21459" async def test_anilist_id() -> None: - media = await AsyncAniList().get(16498) + media = await AsyncAniList().get(id=16498) assert media.title.romaji == "Shingeki no Kyojin" assert media.start_date.year == 2013 assert media.source is MediaSource.MANGA @@ -173,11 +172,11 @@ async def test_anilist_id() -> None: ("Daizen Komatsuda", "Storyboard (ep 23)"), ("You Moriyama", "Key Animation (OP1)"), ] - assert media.site_url == HttpUrl("https://anilist.co/anime/16498") + assert media.site_url.__str__() == "https://anilist.co/anime/16498" async def test_anilist_description() -> None: - media = await AsyncAniList().get(106794) + media = await AsyncAniList().get(id=106794) assert media.title.english == "Bloom Into You Anthology" assert media.start_date.year == 2018 assert media.source is MediaSource.MANGA @@ -190,11 +189,11 @@ async def test_anilist_description() -> None: assert media.relations[0].description.html == BloomIntoYouDescriptions.HTML assert media.relations[0].description.markdown == BloomIntoYouDescriptions.MARKDOWN assert media.relations[0].description.text == BloomIntoYouDescriptions.TEXT - assert media.site_url == HttpUrl("https://anilist.co/manga/106794") + assert media.site_url.__str__() == "https://anilist.co/manga/106794" async def test_anilist_characters() -> None: - media = await AsyncAniList().get(20954) + media = await AsyncAniList().get(id=20954) assert media.title.english == "A Silent Voice" assert media.start_date.year == 2016 assert media.source is MediaSource.MANGA @@ -203,4 +202,4 @@ async def test_anilist_characters() -> None: "Shouya Ishida", "Shouko Nishimiya", ] - assert media.site_url == HttpUrl("https://anilist.co/anime/20954") + assert media.site_url.__str__() == "https://anilist.co/anime/20954" diff --git a/tests/test_async_exceptions.py b/tests/test_async_exceptions.py index 31077ae..2666008 100644 --- a/tests/test_async_exceptions.py +++ b/tests/test_async_exceptions.py @@ -10,14 +10,14 @@ async def test_anilist_bad_search_combo() -> None: with pytest.raises(HTTPStatusError): - await anilist.search("Attack on titan", season_year=1999) + await anilist.get("Attack on titan", season_year=1999) async def test_anilist_wrong_input_types() -> None: with pytest.raises(ValidationError): - await anilist.search(123456789, season_year="hello", type=True) # type: ignore + await anilist.get(id=123456789, season_year="hello", type=True) # type: ignore async def test_anilist_bad_id() -> None: with pytest.raises(HTTPStatusError): - await anilist.get(9999999999) + await anilist.get(id=9999999999) diff --git a/tests/test_exceptions.py b/tests/test_exceptions.py index 3ddfdf2..b80a665 100644 --- a/tests/test_exceptions.py +++ b/tests/test_exceptions.py @@ -10,14 +10,14 @@ def test_anilist_bad_search_combo() -> None: with pytest.raises(HTTPStatusError): - anilist.search("Attack on titan", season_year=1999) + anilist.get("Attack on titan", season_year=1999) def test_anilist_wrong_input_types() -> None: with pytest.raises(ValidationError): - anilist.search(123456789, season_year="hello", type=True) # type: ignore + anilist.get(id=123456789, season_year="hello", type=True) # type: ignore def test_anilist_bad_id() -> None: with pytest.raises(HTTPStatusError): - anilist.get(9999999999) + anilist.get(id=9999999999) diff --git a/tests/test_models.py b/tests/test_models.py index ec21a07..d8f95ac 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -5,4 +5,9 @@ def test_fuzzy_date() -> None: assert FuzzyDate(year=2023, month=1, day=4).iso_format() == "2023-01-04" assert FuzzyDate(year=2023, month=1).iso_format() == "2023-01" assert FuzzyDate(year=2023).iso_format() == "2023" - assert FuzzyDate().iso_format() == "" + + assert FuzzyDate(year=2023, month=1, day=4).as_int() == 20230104 + assert FuzzyDate(year=2023, month=1).as_int() == 20230100 + assert FuzzyDate(year=2023).as_int() == 20230000 + + assert FuzzyDate().iso_format() == "" \ No newline at end of file From f0913891cfe87801a5e4d69ccf89281e61096e4d Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:39:03 +0530 Subject: [PATCH 2/6] chore: remove redundant test, add new tests --- src/pyanilist/_parser.py | 2 +- src/pyanilist/_utils.py | 2 +- tests/test_anilist.py | 19 +------------------ tests/test_async_anilist.py | 19 +------------------ tests/test_utils.py | 21 ++++++++++++++++++++- 5 files changed, 24 insertions(+), 39 deletions(-) diff --git a/src/pyanilist/_parser.py b/src/pyanilist/_parser.py index dbe1ec1..aa1133f 100644 --- a/src/pyanilist/_parser.py +++ b/src/pyanilist/_parser.py @@ -4,7 +4,7 @@ from ._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter -if TYPE_CHECKING: +if TYPE_CHECKING: # pragma: no cover from httpx import Response def process_description(dictionary: dict[str, Any]) -> dict[str, Any]: diff --git a/src/pyanilist/_utils.py b/src/pyanilist/_utils.py index b61080d..d717332 100644 --- a/src/pyanilist/_utils.py +++ b/src/pyanilist/_utils.py @@ -183,7 +183,7 @@ def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: for key, value in vars.items(): if value is not None: if isinstance(value, Iterable) and not isinstance(value, str): - value = tuple(value) + value = set(value) query_vars[casing[key]] = value return query_vars \ No newline at end of file diff --git a/tests/test_anilist.py b/tests/test_anilist.py index 10ded63..b50a969 100644 --- a/tests/test_anilist.py +++ b/tests/test_anilist.py @@ -75,24 +75,7 @@ def test_anilist_manga() -> None: assert media.site_url.__str__() == "https://anilist.co/manga/53390" -def test_anilist_with_some_constraints() -> None: - media = AniList().get( - "violet evergarden", type=MediaType.MANGA, format=MediaFormat.NOVEL, status=MediaStatus.FINISHED - ) - assert media.title.romaji == "Violet Evergarden" - assert media.start_date.year == 2015 - assert media.start_date.iso_format() == "2015-12-25" - assert media.end_date.iso_format() == "2016-12-26" - assert media.source is MediaSource.ORIGINAL - assert media.type is MediaType.MANGA - assert [(staff.name.full, staff.role) for staff in media.staff] == [ - ("Akiko Takase", "Illustration"), - ("Kana Akatsuki", "Story"), - ] - assert media.site_url.__str__() == "https://anilist.co/manga/97298" - - -def test_anilist_with_all_constraints() -> None: +def test_anilist_with_constraints() -> None: media = AniList().get( "My Hero Academia", season=MediaSeason.SPRING, diff --git a/tests/test_async_anilist.py b/tests/test_async_anilist.py index f5ecae0..35ac332 100644 --- a/tests/test_async_anilist.py +++ b/tests/test_async_anilist.py @@ -75,24 +75,7 @@ async def test_anilist_manga() -> None: assert media.site_url.__str__() == "https://anilist.co/manga/53390" -async def test_anilist_with_some_constraints() -> None: - media = await AsyncAniList().get( - "violet evergarden", type=MediaType.MANGA, format=MediaFormat.NOVEL, status=MediaStatus.FINISHED - ) - assert media.title.romaji == "Violet Evergarden" - assert media.start_date.year == 2015 - assert media.start_date.iso_format() == "2015-12-25" - assert media.end_date.iso_format() == "2016-12-26" - assert media.source is MediaSource.ORIGINAL - assert media.type is MediaType.MANGA - assert [(staff.name.full, staff.role) for staff in media.staff] == [ - ("Akiko Takase", "Illustration"), - ("Kana Akatsuki", "Story"), - ] - assert media.site_url.__str__() == "https://anilist.co/manga/97298" - - -async def test_anilist_with_all_constraints() -> None: +async def test_anilist_with_constraints() -> None: media = await AsyncAniList().get( "My Hero Academia", season=MediaSeason.SPRING, diff --git a/tests/test_utils.py b/tests/test_utils.py index dfa4f99..4ed48d5 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,4 +1,5 @@ -from pyanilist._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter +from pyanilist._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter, query_variables_constructor +from pyanilist import MediaSource from .mock_descriptions import BloomIntoYouAnthologyDescriptions @@ -105,3 +106,21 @@ def test_formatters() -> None: assert markdown_formatter(None) is None assert text_formatter(None) is None # fmt: on + + +def test_query_variables_constructor() -> None: + kwargs = { + "id": 123456, + "is_licensed": True, + "search": "Attack on Titan", + "id_not_in": [1, 2, 3, 4, 5, 5, 5], + "source_in": [MediaSource.ANIME, MediaSource.ANIME, MediaSource.MANGA], + } + + assert query_variables_constructor(kwargs) == { + "id": 123456, + "isLicensed": True, + "search": "Attack on Titan", + "id_not_in": {1, 2, 3, 4, 5}, + "source_in": {MediaSource.ANIME, MediaSource.MANGA}, + } \ No newline at end of file From 9e881005fa4db989f0e47c47d1040144ba053f52 Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Thu, 4 Jul 2024 17:47:54 +0530 Subject: [PATCH 3/6] chore: format --- .pre-commit-config.yaml | 4 +- poetry.lock | 875 ++++++++++++++++---------------- pyproject.toml | 27 +- src/pyanilist/_clients/_sync.py | 6 +- src/pyanilist/_compat.py | 1 + src/pyanilist/_models.py | 2 +- src/pyanilist/_parser.py | 6 +- src/pyanilist/_utils.py | 5 +- src/pyanilist/_version.py | 1 + tests/test_anilist.py | 2 +- tests/test_models.py | 2 +- tests/test_utils.py | 11 +- 12 files changed, 468 insertions(+), 474 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 224901b..31f1414 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,12 +1,12 @@ --- repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.5 + rev: v0.5.0 hooks: - id: ruff args: ['--fix'] - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.3.5 + rev: v0.5.0 hooks: - id: ruff-format - repo: https://github.com/python-poetry/poetry diff --git a/poetry.lock b/poetry.lock index 8fa481f..98e908a 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,25 +1,25 @@ -# This file is automatically @generated by Poetry 1.8.3 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 = "annotated-types" -version = "0.6.0" +version = "0.7.0" description = "Reusable constraint types to use with typing.Annotated" optional = false python-versions = ">=3.8" files = [ - {file = "annotated_types-0.6.0-py3-none-any.whl", hash = "sha256:0641064de18ba7a25dee8f96403ebc39113d0cb953a01429249d5c7564666a43"}, - {file = "annotated_types-0.6.0.tar.gz", hash = "sha256:563339e807e53ffd9c267e99fc6d9ea23eb8443c08f112651963e24e22f84a5d"}, + {file = "annotated_types-0.7.0-py3-none-any.whl", hash = "sha256:1f02e8b43a8fbbc3f3e0d4f0f4bfc8131bcb4eebe8849b8e5c773f3a1c582a53"}, + {file = "annotated_types-0.7.0.tar.gz", hash = "sha256:aff07c09a53a08bc8cfccb9c85b05f1aa9a2a6f23728d790723543408344ce89"}, ] [[package]] name = "anyio" -version = "4.3.0" +version = "4.4.0" description = "High level compatibility layer for multiple asynchronous event loop implementations" optional = false python-versions = ">=3.8" files = [ - {file = "anyio-4.3.0-py3-none-any.whl", hash = "sha256:048e05d0f6caeed70d731f3db756d35dcc1f35747c8c403364a8332c630441b8"}, - {file = "anyio-4.3.0.tar.gz", hash = "sha256:f75253795a87df48568485fd18cdd2a3fa5c4f7c5be8e5e36637733fce06fed6"}, + {file = "anyio-4.4.0-py3-none-any.whl", hash = "sha256:c1b2d8f46a8a812513012e1107cb0e68c17159a7a594208005a57dc776e1bdc7"}, + {file = "anyio-4.4.0.tar.gz", hash = "sha256:5aadc6a1bbb7cdb0bede386cac5e2940f5e2ff3aa20277e991cf028e0585ce94"}, ] [package.dependencies] @@ -35,13 +35,13 @@ trio = ["trio (>=0.23)"] [[package]] name = "babel" -version = "2.14.0" +version = "2.15.0" description = "Internationalization utilities" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "Babel-2.14.0-py3-none-any.whl", hash = "sha256:efb1a25b7118e67ce3a259bed20545c29cb68be8ad2c784c83689981b7a57287"}, - {file = "Babel-2.14.0.tar.gz", hash = "sha256:6919867db036398ba21eb5c7a0f6b28ab8cbc3ae7a73a44ebe34ae74a4e7d363"}, + {file = "Babel-2.15.0-py3-none-any.whl", hash = "sha256:08706bdad8d0a3413266ab61bd6c34d0c28d6e1e7badf40a2cebe67644e2e1fb"}, + {file = "babel-2.15.0.tar.gz", hash = "sha256:8daf0e265d05768bc6c7a314cf1321e9a123afc328cc635c18622a2f30a04413"}, ] [package.extras] @@ -71,13 +71,13 @@ files = [ [[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]] @@ -217,63 +217,63 @@ files = [ [[package]] name = "coverage" -version = "7.5.0" +version = "7.5.4" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.5.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:432949a32c3e3f820af808db1833d6d1631664d53dd3ce487aa25d574e18ad1c"}, - {file = "coverage-7.5.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2bd7065249703cbeb6d4ce679c734bef0ee69baa7bff9724361ada04a15b7e3b"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bbfe6389c5522b99768a93d89aca52ef92310a96b99782973b9d11e80511f932"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:39793731182c4be939b4be0cdecde074b833f6171313cf53481f869937129ed3"}, - {file = "coverage-7.5.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85a5dbe1ba1bf38d6c63b6d2c42132d45cbee6d9f0c51b52c59aa4afba057517"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:357754dcdfd811462a725e7501a9b4556388e8ecf66e79df6f4b988fa3d0b39a"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:a81eb64feded34f40c8986869a2f764f0fe2db58c0530d3a4afbcde50f314880"}, - {file = "coverage-7.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:51431d0abbed3a868e967f8257c5faf283d41ec882f58413cf295a389bb22e58"}, - {file = "coverage-7.5.0-cp310-cp310-win32.whl", hash = "sha256:f609ebcb0242d84b7adeee2b06c11a2ddaec5464d21888b2c8255f5fd6a98ae4"}, - {file = "coverage-7.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:6782cd6216fab5a83216cc39f13ebe30adfac2fa72688c5a4d8d180cd52e8f6a"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:e768d870801f68c74c2b669fc909839660180c366501d4cc4b87efd6b0eee375"}, - {file = "coverage-7.5.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:84921b10aeb2dd453247fd10de22907984eaf80901b578a5cf0bb1e279a587cb"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:710c62b6e35a9a766b99b15cdc56d5aeda0914edae8bb467e9c355f75d14ee95"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c379cdd3efc0658e652a14112d51a7668f6bfca7445c5a10dee7eabecabba19d"}, - {file = "coverage-7.5.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fea9d3ca80bcf17edb2c08a4704259dadac196fe5e9274067e7a20511fad1743"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:41327143c5b1d715f5f98a397608f90ab9ebba606ae4e6f3389c2145410c52b1"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:565b2e82d0968c977e0b0f7cbf25fd06d78d4856289abc79694c8edcce6eb2de"}, - {file = "coverage-7.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:cf3539007202ebfe03923128fedfdd245db5860a36810136ad95a564a2fdffff"}, - {file = "coverage-7.5.0-cp311-cp311-win32.whl", hash = "sha256:bf0b4b8d9caa8d64df838e0f8dcf68fb570c5733b726d1494b87f3da85db3a2d"}, - {file = "coverage-7.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:9c6384cc90e37cfb60435bbbe0488444e54b98700f727f16f64d8bfda0b84656"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:fed7a72d54bd52f4aeb6c6e951f363903bd7d70bc1cad64dd1f087980d309ab9"}, - {file = "coverage-7.5.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cbe6581fcff7c8e262eb574244f81f5faaea539e712a058e6707a9d272fe5b64"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad97ec0da94b378e593ef532b980c15e377df9b9608c7c6da3506953182398af"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd4bacd62aa2f1a1627352fe68885d6ee694bdaebb16038b6e680f2924a9b2cc"}, - {file = "coverage-7.5.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:adf032b6c105881f9d77fa17d9eebe0ad1f9bfb2ad25777811f97c5362aa07f2"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4ba01d9ba112b55bfa4b24808ec431197bb34f09f66f7cb4fd0258ff9d3711b1"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:f0bfe42523893c188e9616d853c47685e1c575fe25f737adf473d0405dcfa7eb"}, - {file = "coverage-7.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a9a7ef30a1b02547c1b23fa9a5564f03c9982fc71eb2ecb7f98c96d7a0db5cf2"}, - {file = "coverage-7.5.0-cp312-cp312-win32.whl", hash = "sha256:3c2b77f295edb9fcdb6a250f83e6481c679335ca7e6e4a955e4290350f2d22a4"}, - {file = "coverage-7.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:427e1e627b0963ac02d7c8730ca6d935df10280d230508c0ba059505e9233475"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:9dd88fce54abbdbf4c42fb1fea0e498973d07816f24c0e27a1ecaf91883ce69e"}, - {file = "coverage-7.5.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a898c11dca8f8c97b467138004a30133974aacd572818c383596f8d5b2eb04a9"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07dfdd492d645eea1bd70fb1d6febdcf47db178b0d99161d8e4eed18e7f62fe7"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d3d117890b6eee85887b1eed41eefe2e598ad6e40523d9f94c4c4b213258e4a4"}, - {file = "coverage-7.5.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6afd2e84e7da40fe23ca588379f815fb6dbbb1b757c883935ed11647205111cb"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:a9960dd1891b2ddf13a7fe45339cd59ecee3abb6b8326d8b932d0c5da208104f"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:ced268e82af993d7801a9db2dbc1d2322e786c5dc76295d8e89473d46c6b84d4"}, - {file = "coverage-7.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e7c211f25777746d468d76f11719e64acb40eed410d81c26cefac641975beb88"}, - {file = "coverage-7.5.0-cp38-cp38-win32.whl", hash = "sha256:262fffc1f6c1a26125d5d573e1ec379285a3723363f3bd9c83923c9593a2ac25"}, - {file = "coverage-7.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:eed462b4541c540d63ab57b3fc69e7d8c84d5957668854ee4e408b50e92ce26a"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:d0194d654e360b3e6cc9b774e83235bae6b9b2cac3be09040880bb0e8a88f4a1"}, - {file = "coverage-7.5.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:33c020d3322662e74bc507fb11488773a96894aa82a622c35a5a28673c0c26f5"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0cbdf2cae14a06827bec50bd58e49249452d211d9caddd8bd80e35b53cb04631"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3235d7c781232e525b0761730e052388a01548bd7f67d0067a253887c6e8df46"}, - {file = "coverage-7.5.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:db2de4e546f0ec4b2787d625e0b16b78e99c3e21bc1722b4977c0dddf11ca84e"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4d0e206259b73af35c4ec1319fd04003776e11e859936658cb6ceffdeba0f5be"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:2055c4fb9a6ff624253d432aa471a37202cd8f458c033d6d989be4499aed037b"}, - {file = "coverage-7.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:075299460948cd12722a970c7eae43d25d37989da682997687b34ae6b87c0ef0"}, - {file = "coverage-7.5.0-cp39-cp39-win32.whl", hash = "sha256:280132aada3bc2f0fac939a5771db4fbb84f245cb35b94fae4994d4c1f80dae7"}, - {file = "coverage-7.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:c58536f6892559e030e6924896a44098bc1290663ea12532c78cef71d0df8493"}, - {file = "coverage-7.5.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:2b57780b51084d5223eee7b59f0d4911c31c16ee5aa12737c7a02455829ff067"}, - {file = "coverage-7.5.0.tar.gz", hash = "sha256:cf62d17310f34084c59c01e027259076479128d11e4661bb6c9acb38c5e19bb8"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:6cfb5a4f556bb51aba274588200a46e4dd6b505fb1a5f8c5ae408222eb416f99"}, + {file = "coverage-7.5.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:2174e7c23e0a454ffe12267a10732c273243b4f2d50d07544a91198f05c48f47"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2214ee920787d85db1b6a0bd9da5f8503ccc8fcd5814d90796c2f2493a2f4d2e"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1137f46adb28e3813dec8c01fefadcb8c614f33576f672962e323b5128d9a68d"}, + {file = "coverage-7.5.4-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b385d49609f8e9efc885790a5a0e89f2e3ae042cdf12958b6034cc442de428d3"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:b4a474f799456e0eb46d78ab07303286a84a3140e9700b9e154cfebc8f527016"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:5cd64adedf3be66f8ccee418473c2916492d53cbafbfcff851cbec5a8454b136"}, + {file = "coverage-7.5.4-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:e564c2cf45d2f44a9da56f4e3a26b2236504a496eb4cb0ca7221cd4cc7a9aca9"}, + {file = "coverage-7.5.4-cp310-cp310-win32.whl", hash = "sha256:7076b4b3a5f6d2b5d7f1185fde25b1e54eb66e647a1dfef0e2c2bfaf9b4c88c8"}, + {file = "coverage-7.5.4-cp310-cp310-win_amd64.whl", hash = "sha256:018a12985185038a5b2bcafab04ab833a9a0f2c59995b3cec07e10074c78635f"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:db14f552ac38f10758ad14dd7b983dbab424e731588d300c7db25b6f89e335b5"}, + {file = "coverage-7.5.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3257fdd8e574805f27bb5342b77bc65578e98cbc004a92232106344053f319ba"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3a6612c99081d8d6134005b1354191e103ec9705d7ba2754e848211ac8cacc6b"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d45d3cbd94159c468b9b8c5a556e3f6b81a8d1af2a92b77320e887c3e7a5d080"}, + {file = "coverage-7.5.4-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ed550e7442f278af76d9d65af48069f1fb84c9f745ae249c1a183c1e9d1b025c"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:7a892be37ca35eb5019ec85402c3371b0f7cda5ab5056023a7f13da0961e60da"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:8192794d120167e2a64721d88dbd688584675e86e15d0569599257566dec9bf0"}, + {file = "coverage-7.5.4-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:820bc841faa502e727a48311948e0461132a9c8baa42f6b2b84a29ced24cc078"}, + {file = "coverage-7.5.4-cp311-cp311-win32.whl", hash = "sha256:6aae5cce399a0f065da65c7bb1e8abd5c7a3043da9dceb429ebe1b289bc07806"}, + {file = "coverage-7.5.4-cp311-cp311-win_amd64.whl", hash = "sha256:d2e344d6adc8ef81c5a233d3a57b3c7d5181f40e79e05e1c143da143ccb6377d"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:54317c2b806354cbb2dc7ac27e2b93f97096912cc16b18289c5d4e44fc663233"}, + {file = "coverage-7.5.4-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:042183de01f8b6d531e10c197f7f0315a61e8d805ab29c5f7b51a01d62782747"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a6bb74ed465d5fb204b2ec41d79bcd28afccf817de721e8a807d5141c3426638"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b3d45ff86efb129c599a3b287ae2e44c1e281ae0f9a9bad0edc202179bcc3a2e"}, + {file = "coverage-7.5.4-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5013ed890dc917cef2c9f765c4c6a8ae9df983cd60dbb635df8ed9f4ebc9f555"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:1014fbf665fef86cdfd6cb5b7371496ce35e4d2a00cda501cf9f5b9e6fced69f"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:3684bc2ff328f935981847082ba4fdc950d58906a40eafa93510d1b54c08a66c"}, + {file = "coverage-7.5.4-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:581ea96f92bf71a5ec0974001f900db495488434a6928a2ca7f01eee20c23805"}, + {file = "coverage-7.5.4-cp312-cp312-win32.whl", hash = "sha256:73ca8fbc5bc622e54627314c1a6f1dfdd8db69788f3443e752c215f29fa87a0b"}, + {file = "coverage-7.5.4-cp312-cp312-win_amd64.whl", hash = "sha256:cef4649ec906ea7ea5e9e796e68b987f83fa9a718514fe147f538cfeda76d7a7"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cdd31315fc20868c194130de9ee6bfd99755cc9565edff98ecc12585b90be882"}, + {file = "coverage-7.5.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:02ff6e898197cc1e9fa375581382b72498eb2e6d5fc0b53f03e496cfee3fac6d"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d05c16cf4b4c2fc880cb12ba4c9b526e9e5d5bb1d81313d4d732a5b9fe2b9d53"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c5986ee7ea0795a4095ac4d113cbb3448601efca7f158ec7f7087a6c705304e4"}, + {file = "coverage-7.5.4-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5df54843b88901fdc2f598ac06737f03d71168fd1175728054c8f5a2739ac3e4"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:ab73b35e8d109bffbda9a3e91c64e29fe26e03e49addf5b43d85fc426dde11f9"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:aea072a941b033813f5e4814541fc265a5c12ed9720daef11ca516aeacd3bd7f"}, + {file = "coverage-7.5.4-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:16852febd96acd953b0d55fc842ce2dac1710f26729b31c80b940b9afcd9896f"}, + {file = "coverage-7.5.4-cp38-cp38-win32.whl", hash = "sha256:8f894208794b164e6bd4bba61fc98bf6b06be4d390cf2daacfa6eca0a6d2bb4f"}, + {file = "coverage-7.5.4-cp38-cp38-win_amd64.whl", hash = "sha256:e2afe743289273209c992075a5a4913e8d007d569a406ffed0bd080ea02b0633"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:b95c3a8cb0463ba9f77383d0fa8c9194cf91f64445a63fc26fb2327e1e1eb088"}, + {file = "coverage-7.5.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:3d7564cc09dd91b5a6001754a5b3c6ecc4aba6323baf33a12bd751036c998be4"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:44da56a2589b684813f86d07597fdf8a9c6ce77f58976727329272f5a01f99f7"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e16f3d6b491c48c5ae726308e6ab1e18ee830b4cdd6913f2d7f77354b33f91c8"}, + {file = "coverage-7.5.4-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dbc5958cb471e5a5af41b0ddaea96a37e74ed289535e8deca404811f6cb0bc3d"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:a04e990a2a41740b02d6182b498ee9796cf60eefe40cf859b016650147908029"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:ddbd2f9713a79e8e7242d7c51f1929611e991d855f414ca9996c20e44a895f7c"}, + {file = "coverage-7.5.4-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:b1ccf5e728ccf83acd313c89f07c22d70d6c375a9c6f339233dcf792094bcbf7"}, + {file = "coverage-7.5.4-cp39-cp39-win32.whl", hash = "sha256:56b4eafa21c6c175b3ede004ca12c653a88b6f922494b023aeb1e836df953ace"}, + {file = "coverage-7.5.4-cp39-cp39-win_amd64.whl", hash = "sha256:65e528e2e921ba8fd67d9055e6b9f9e34b21ebd6768ae1c1723f4ea6ace1234d"}, + {file = "coverage-7.5.4-pp38.pp39.pp310-none-any.whl", hash = "sha256:79b356f3dd5b26f3ad23b35c75dbdaf1f9e2450b6bcefc6d0825ea0aa3f86ca5"}, + {file = "coverage-7.5.4.tar.gz", hash = "sha256:a44963520b069e12789d0faea4e9fdb1e410cdc4aab89d94f7f55cbb7fef0353"}, ] [package.extras] @@ -320,18 +320,18 @@ test = ["pytest (>=6)"] [[package]] name = "filelock" -version = "3.13.4" +version = "3.15.4" description = "A platform independent file lock." optional = false python-versions = ">=3.8" files = [ - {file = "filelock-3.13.4-py3-none-any.whl", hash = "sha256:404e5e9253aa60ad457cae1be07c0f0ca90a63931200a47d9b6a6af84fd7b45f"}, - {file = "filelock-3.13.4.tar.gz", hash = "sha256:d13f466618bfde72bd2c18255e269f72542c6e70e7bac83a0232d6b1cc5c8cf4"}, + {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]] @@ -353,13 +353,13 @@ dev = ["flake8", "markdown", "twine", "wheel"] [[package]] name = "griffe" -version = "0.44.0" +version = "0.47.0" description = "Signatures for entire Python programs. Extract the structure, the frame, the skeleton of your project, to generate API documentation or find breaking changes in your API." optional = false python-versions = ">=3.8" files = [ - {file = "griffe-0.44.0-py3-none-any.whl", hash = "sha256:8a4471c469ba980b87c843f1168850ce39d0c1d0c7be140dca2480f76c8e5446"}, - {file = "griffe-0.44.0.tar.gz", hash = "sha256:34aee1571042f9bf00529bc715de4516fb6f482b164e90d030300601009e0223"}, + {file = "griffe-0.47.0-py3-none-any.whl", hash = "sha256:07a2fd6a8c3d21d0bbb0decf701d62042ccc8a576645c7f8799fe1f10de2b2de"}, + {file = "griffe-0.47.0.tar.gz", hash = "sha256:95119a440a3c932b13293538bdbc405bee4c36428547553dc6b327e7e7d35e5a"}, ] [package.dependencies] @@ -458,22 +458,22 @@ files = [ [[package]] name = "importlib-metadata" -version = "7.1.0" +version = "8.0.0" description = "Read metadata from Python packages" optional = false python-versions = ">=3.8" files = [ - {file = "importlib_metadata-7.1.0-py3-none-any.whl", hash = "sha256:30962b96c0c223483ed6cc7280e7f0199feb01a0e40cfae4d4450fc6fab1f570"}, - {file = "importlib_metadata-7.1.0.tar.gz", hash = "sha256:b78938b926ee8d5f020fc4772d487045805a55ddbad2ecf21c6d60938dc7fcd2"}, + {file = "importlib_metadata-8.0.0-py3-none-any.whl", hash = "sha256:15584cf2b1bf449d98ff8a6ff1abef57bf20f3ac6454f431736cd3e660921b2f"}, + {file = "importlib_metadata-8.0.0.tar.gz", hash = "sha256:188bd24e4c346d3f0a933f275c2fec67050326a856b9a359881d7c2a697e8812"}, ] [package.dependencies] zipp = ">=0.5" [package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "rst.linker (>=1.9)", "sphinx (>=3.5)", "sphinx-lint"] +doc = ["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)", "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)"] +test = ["flufl.flake8", "importlib-resources (>=1.3)", "jaraco.test (>=5.4)", "packaging", "pyfakefs", "pytest (>=6,!=8.1.*)", "pytest-checkdocs (>=2.4)", "pytest-cov", "pytest-enabler (>=2.2)", "pytest-mypy", "pytest-perf (>=0.9.2)", "pytest-ruff (>=0.2.1)"] [[package]] name = "iniconfig" @@ -488,13 +488,13 @@ files = [ [[package]] name = "jinja2" -version = "3.1.3" +version = "3.1.4" description = "A very fast and expressive template engine." optional = false python-versions = ">=3.7" files = [ - {file = "Jinja2-3.1.3-py3-none-any.whl", hash = "sha256:7d6d50dd97d52cbc355597bd845fabfbac3f551e1f99619e39a35ce8c370b5fa"}, - {file = "Jinja2-3.1.3.tar.gz", hash = "sha256:ac8bd6544d4bb2c9792bf3a159e80bba8fda7f07e81bc3aed565432d5925ba90"}, + {file = "jinja2-3.1.4-py3-none-any.whl", hash = "sha256:bc5dd2abb727a5319567b7a813e6a2e7318c39f4f487cfe6c89c6f9c7d25197d"}, + {file = "jinja2-3.1.4.tar.gz", hash = "sha256:4a3aee7acbbe7303aede8e9648d13b8bf88a429282aa6122a993f0ac800cb369"}, ] [package.dependencies] @@ -603,34 +603,34 @@ files = [ [[package]] name = "mkdocs" -version = "1.5.3" +version = "1.6.0" description = "Project documentation with Markdown." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "mkdocs-1.5.3-py3-none-any.whl", hash = "sha256:3b3a78e736b31158d64dbb2f8ba29bd46a379d0c6e324c2246c3bc3d2189cfc1"}, - {file = "mkdocs-1.5.3.tar.gz", hash = "sha256:eb7c99214dcb945313ba30426c2451b735992c73c2e10838f76d09e39ff4d0e2"}, + {file = "mkdocs-1.6.0-py3-none-any.whl", hash = "sha256:1eb5cb7676b7d89323e62b56235010216319217d4af5ddc543a91beb8d125ea7"}, + {file = "mkdocs-1.6.0.tar.gz", hash = "sha256:a73f735824ef83a4f3bcb7a231dcab23f5a838f88b7efc54a0eef5fbdbc3c512"}, ] [package.dependencies] click = ">=7.0" colorama = {version = ">=0.4", markers = "platform_system == \"Windows\""} ghp-import = ">=1.0" -importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +importlib-metadata = {version = ">=4.4", markers = "python_version < \"3.10\""} jinja2 = ">=2.11.1" -markdown = ">=3.2.1" +markdown = ">=3.3.6" markupsafe = ">=2.0.1" mergedeep = ">=1.3.4" +mkdocs-get-deps = ">=0.2.0" packaging = ">=20.5" pathspec = ">=0.11.1" -platformdirs = ">=2.2.0" pyyaml = ">=5.1" pyyaml-env-tag = ">=0.1" watchdog = ">=2.0" [package.extras] i18n = ["babel (>=2.9.0)"] -min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.3)", "jinja2 (==2.11.1)", "markdown (==3.2.1)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "packaging (==20.5)", "pathspec (==0.11.1)", "platformdirs (==2.2.0)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "typing-extensions (==3.10)", "watchdog (==2.0)"] +min-versions = ["babel (==2.9.0)", "click (==7.0)", "colorama (==0.4)", "ghp-import (==1.0)", "importlib-metadata (==4.4)", "jinja2 (==2.11.1)", "markdown (==3.3.6)", "markupsafe (==2.0.1)", "mergedeep (==1.3.4)", "mkdocs-get-deps (==0.2.0)", "packaging (==20.5)", "pathspec (==0.11.1)", "pyyaml (==5.1)", "pyyaml-env-tag (==0.1)", "watchdog (==2.0)"] [[package]] name = "mkdocs-autorefs" @@ -648,15 +648,32 @@ Markdown = ">=3.3" markupsafe = ">=2.0.1" mkdocs = ">=1.1" +[[package]] +name = "mkdocs-get-deps" +version = "0.2.0" +description = "MkDocs extension that lists all dependencies according to a mkdocs.yml file" +optional = false +python-versions = ">=3.8" +files = [ + {file = "mkdocs_get_deps-0.2.0-py3-none-any.whl", hash = "sha256:2bf11d0b133e77a0dd036abeeb06dec8775e46efa526dc70667d8863eefc6134"}, + {file = "mkdocs_get_deps-0.2.0.tar.gz", hash = "sha256:162b3d129c7fad9b19abfdcb9c1458a651628e4b1dea628ac68790fb3061c60c"}, +] + +[package.dependencies] +importlib-metadata = {version = ">=4.3", markers = "python_version < \"3.10\""} +mergedeep = ">=1.3.4" +platformdirs = ">=2.2.0" +pyyaml = ">=5.1" + [[package]] name = "mkdocs-material" -version = "9.5.18" +version = "9.5.28" description = "Documentation that simply works" optional = false python-versions = ">=3.8" files = [ - {file = "mkdocs_material-9.5.18-py3-none-any.whl", hash = "sha256:1e0e27fc9fe239f9064318acf548771a4629d5fd5dfd45444fd80a953fe21eb4"}, - {file = "mkdocs_material-9.5.18.tar.gz", hash = "sha256:a43f470947053fa2405c33995f282d24992c752a50114f23f30da9d8d0c57e62"}, + {file = "mkdocs_material-9.5.28-py3-none-any.whl", hash = "sha256:ff48b11b2a9f705dd210409ec3b418ab443dd36d96915bcba45a41f10ea27bfd"}, + {file = "mkdocs_material-9.5.28.tar.gz", hash = "sha256:9cba305283ad1600e3d0a67abe72d7a058b54793b47be39930911a588fe0336b"}, ] [package.dependencies] @@ -664,7 +681,7 @@ babel = ">=2.10,<3.0" colorama = ">=0.4,<1.0" jinja2 = ">=3.0,<4.0" markdown = ">=3.2,<4.0" -mkdocs = ">=1.5.3,<1.6.0" +mkdocs = ">=1.6,<2.0" mkdocs-material-extensions = ">=1.3,<2.0" paginate = ">=0.5,<1.0" pygments = ">=2.16,<3.0" @@ -734,38 +751,38 @@ mkdocstrings = ">=0.24.2" [[package]] name = "mypy" -version = "1.9.0" +version = "1.10.1" description = "Optional static typing for Python" optional = false python-versions = ">=3.8" files = [ - {file = "mypy-1.9.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:f8a67616990062232ee4c3952f41c779afac41405806042a8126fe96e098419f"}, - {file = "mypy-1.9.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d357423fa57a489e8c47b7c85dfb96698caba13d66e086b412298a1a0ea3b0ed"}, - {file = "mypy-1.9.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:49c87c15aed320de9b438ae7b00c1ac91cd393c1b854c2ce538e2a72d55df150"}, - {file = "mypy-1.9.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:48533cdd345c3c2e5ef48ba3b0d3880b257b423e7995dada04248725c6f77374"}, - {file = "mypy-1.9.0-cp310-cp310-win_amd64.whl", hash = "sha256:4d3dbd346cfec7cb98e6cbb6e0f3c23618af826316188d587d1c1bc34f0ede03"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:653265f9a2784db65bfca694d1edd23093ce49740b2244cde583aeb134c008f3"}, - {file = "mypy-1.9.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3a3c007ff3ee90f69cf0a15cbcdf0995749569b86b6d2f327af01fd1b8aee9dc"}, - {file = "mypy-1.9.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2418488264eb41f69cc64a69a745fad4a8f86649af4b1041a4c64ee61fc61129"}, - {file = "mypy-1.9.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:68edad3dc7d70f2f17ae4c6c1b9471a56138ca22722487eebacfd1eb5321d612"}, - {file = "mypy-1.9.0-cp311-cp311-win_amd64.whl", hash = "sha256:85ca5fcc24f0b4aeedc1d02f93707bccc04733f21d41c88334c5482219b1ccb3"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aceb1db093b04db5cd390821464504111b8ec3e351eb85afd1433490163d60cd"}, - {file = "mypy-1.9.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0235391f1c6f6ce487b23b9dbd1327b4ec33bb93934aa986efe8a9563d9349e6"}, - {file = "mypy-1.9.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4d5ddc13421ba3e2e082a6c2d74c2ddb3979c39b582dacd53dd5d9431237185"}, - {file = "mypy-1.9.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:190da1ee69b427d7efa8aa0d5e5ccd67a4fb04038c380237a0d96829cb157913"}, - {file = "mypy-1.9.0-cp312-cp312-win_amd64.whl", hash = "sha256:fe28657de3bfec596bbeef01cb219833ad9d38dd5393fc649f4b366840baefe6"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e54396d70be04b34f31d2edf3362c1edd023246c82f1730bbf8768c28db5361b"}, - {file = "mypy-1.9.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5e6061f44f2313b94f920e91b204ec600982961e07a17e0f6cd83371cb23f5c2"}, - {file = "mypy-1.9.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81a10926e5473c5fc3da8abb04119a1f5811a236dc3a38d92015cb1e6ba4cb9e"}, - {file = "mypy-1.9.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:b685154e22e4e9199fc95f298661deea28aaede5ae16ccc8cbb1045e716b3e04"}, - {file = "mypy-1.9.0-cp38-cp38-win_amd64.whl", hash = "sha256:5d741d3fc7c4da608764073089e5f58ef6352bedc223ff58f2f038c2c4698a89"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:587ce887f75dd9700252a3abbc9c97bbe165a4a630597845c61279cf32dfbf02"}, - {file = "mypy-1.9.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:f88566144752999351725ac623471661c9d1cd8caa0134ff98cceeea181789f4"}, - {file = "mypy-1.9.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:61758fabd58ce4b0720ae1e2fea5cfd4431591d6d590b197775329264f86311d"}, - {file = "mypy-1.9.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e49499be624dead83927e70c756970a0bc8240e9f769389cdf5714b0784ca6bf"}, - {file = "mypy-1.9.0-cp39-cp39-win_amd64.whl", hash = "sha256:571741dc4194b4f82d344b15e8837e8c5fcc462d66d076748142327626a1b6e9"}, - {file = "mypy-1.9.0-py3-none-any.whl", hash = "sha256:a260627a570559181a9ea5de61ac6297aa5af202f06fd7ab093ce74e7181e43e"}, - {file = "mypy-1.9.0.tar.gz", hash = "sha256:3cc5da0127e6a478cddd906068496a97a7618a21ce9b54bde5bf7e539c7af974"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e36f229acfe250dc660790840916eb49726c928e8ce10fbdf90715090fe4ae02"}, + {file = "mypy-1.10.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:51a46974340baaa4145363b9e051812a2446cf583dfaeba124af966fa44593f7"}, + {file = "mypy-1.10.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:901c89c2d67bba57aaaca91ccdb659aa3a312de67f23b9dfb059727cce2e2e0a"}, + {file = "mypy-1.10.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:0cd62192a4a32b77ceb31272d9e74d23cd88c8060c34d1d3622db3267679a5d9"}, + {file = "mypy-1.10.1-cp310-cp310-win_amd64.whl", hash = "sha256:a2cbc68cb9e943ac0814c13e2452d2046c2f2b23ff0278e26599224cf164e78d"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:bd6f629b67bb43dc0d9211ee98b96d8dabc97b1ad38b9b25f5e4c4d7569a0c6a"}, + {file = "mypy-1.10.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a1bbb3a6f5ff319d2b9d40b4080d46cd639abe3516d5a62c070cf0114a457d84"}, + {file = "mypy-1.10.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b8edd4e9bbbc9d7b79502eb9592cab808585516ae1bcc1446eb9122656c6066f"}, + {file = "mypy-1.10.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6166a88b15f1759f94a46fa474c7b1b05d134b1b61fca627dd7335454cc9aa6b"}, + {file = "mypy-1.10.1-cp311-cp311-win_amd64.whl", hash = "sha256:5bb9cd11c01c8606a9d0b83ffa91d0b236a0e91bc4126d9ba9ce62906ada868e"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d8681909f7b44d0b7b86e653ca152d6dff0eb5eb41694e163c6092124f8246d7"}, + {file = "mypy-1.10.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:378c03f53f10bbdd55ca94e46ec3ba255279706a6aacaecac52ad248f98205d3"}, + {file = "mypy-1.10.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6bacf8f3a3d7d849f40ca6caea5c055122efe70e81480c8328ad29c55c69e93e"}, + {file = "mypy-1.10.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:701b5f71413f1e9855566a34d6e9d12624e9e0a8818a5704d74d6b0402e66c04"}, + {file = "mypy-1.10.1-cp312-cp312-win_amd64.whl", hash = "sha256:3c4c2992f6ea46ff7fce0072642cfb62af7a2484efe69017ed8b095f7b39ef31"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:604282c886497645ffb87b8f35a57ec773a4a2721161e709a4422c1636ddde5c"}, + {file = "mypy-1.10.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:37fd87cab83f09842653f08de066ee68f1182b9b5282e4634cdb4b407266bade"}, + {file = "mypy-1.10.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8addf6313777dbb92e9564c5d32ec122bf2c6c39d683ea64de6a1fd98b90fe37"}, + {file = "mypy-1.10.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:5cc3ca0a244eb9a5249c7c583ad9a7e881aa5d7b73c35652296ddcdb33b2b9c7"}, + {file = "mypy-1.10.1-cp38-cp38-win_amd64.whl", hash = "sha256:1b3a2ffce52cc4dbaeee4df762f20a2905aa171ef157b82192f2e2f368eec05d"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:fe85ed6836165d52ae8b88f99527d3d1b2362e0cb90b005409b8bed90e9059b3"}, + {file = "mypy-1.10.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:c2ae450d60d7d020d67ab440c6e3fae375809988119817214440033f26ddf7bf"}, + {file = "mypy-1.10.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6be84c06e6abd72f960ba9a71561c14137a583093ffcf9bbfaf5e613d63fa531"}, + {file = "mypy-1.10.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:2189ff1e39db399f08205e22a797383613ce1cb0cb3b13d8bcf0170e45b96cc3"}, + {file = "mypy-1.10.1-cp39-cp39-win_amd64.whl", hash = "sha256:97a131ee36ac37ce9581f4220311247ab6cba896b4395b9c87af0675a13a755f"}, + {file = "mypy-1.10.1-py3-none-any.whl", hash = "sha256:71d8ac0b906354ebda8ef1673e5fde785936ac1f29ff6987c7483cfbd5a4235a"}, + {file = "mypy-1.10.1.tar.gz", hash = "sha256:1f8f492d7db9e3593ef42d4f115f04e556130f2819ad33ab84551403e97dd4c0"}, ] [package.dependencies] @@ -817,27 +834,24 @@ files = [ [[package]] name = "nodeenv" -version = "1.8.0" +version = "1.9.1" description = "Node.js virtual environment builder" optional = false -python-versions = ">=2.7,!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*" +python-versions = "!=3.0.*,!=3.1.*,!=3.2.*,!=3.3.*,!=3.4.*,!=3.5.*,!=3.6.*,>=2.7" files = [ - {file = "nodeenv-1.8.0-py2.py3-none-any.whl", hash = "sha256:df865724bb3c3adc86b3876fa209771517b0cfe596beff01a92700e0e8be4cec"}, - {file = "nodeenv-1.8.0.tar.gz", hash = "sha256:d51e0c37e64fbf47d017feac3145cdbb58836d7eee8c6f6d3b6880c5456227d2"}, + {file = "nodeenv-1.9.1-py2.py3-none-any.whl", hash = "sha256:ba11c9782d29c27c70ffbdda2d7415098754709be8a7056d79a737cd901155c9"}, + {file = "nodeenv-1.9.1.tar.gz", hash = "sha256:6ec12890a2dab7946721edbfbcd91f3319c6ccc9aec47be7c7e6b7011ee6645f"}, ] -[package.dependencies] -setuptools = "*" - [[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]] @@ -863,13 +877,13 @@ files = [ [[package]] name = "platformdirs" -version = "4.2.1" +version = "4.2.2" description = "A small Python package for determining appropriate platform-specific dirs, e.g. a `user data dir`." optional = false python-versions = ">=3.8" files = [ - {file = "platformdirs-4.2.1-py3-none-any.whl", hash = "sha256:17d5a1161b3fd67b390023cb2d3b026bbd40abde6fdb052dfbd3a29c3ba22ee1"}, - {file = "platformdirs-4.2.1.tar.gz", hash = "sha256:031cd18d4ec63ec53e82dceaac0417d218a6863f7745dfcc9efe7793b7039bdf"}, + {file = "platformdirs-4.2.2-py3-none-any.whl", hash = "sha256:2d7a1657e36a80ea911db832a8a6ece5ee53d8de21edd5cc5879af6530b1bfee"}, + {file = "platformdirs-4.2.2.tar.gz", hash = "sha256:38b7b51f512eed9e84a22788b4bce1de17c0adb134d6becb09836e37d8654cd3"}, ] [package.extras] @@ -894,13 +908,13 @@ testing = ["pytest", "pytest-benchmark"] [[package]] name = "pre-commit" -version = "3.7.0" +version = "3.7.1" description = "A framework for managing and maintaining multi-language pre-commit hooks." optional = false python-versions = ">=3.9" files = [ - {file = "pre_commit-3.7.0-py2.py3-none-any.whl", hash = "sha256:5eae9e10c2b5ac51577c3452ec0a490455c45a0533f7960f993a0d01e59decab"}, - {file = "pre_commit-3.7.0.tar.gz", hash = "sha256:e209d61b8acdcf742404408531f0c37d49d2c734fd7cff2d6076083d191cb060"}, + {file = "pre_commit-3.7.1-py2.py3-none-any.whl", hash = "sha256:fae36fd1d7ad7d6a5a1c0b0d5adb2ed1a3bda5a21bf6c3e5372073d7a11cd4c5"}, + {file = "pre_commit-3.7.1.tar.gz", hash = "sha256:8ca3ad567bc78a4972a3f1a477e94a79d4597e8140a6e0b651c5e33899c3654a"}, ] [package.dependencies] @@ -912,29 +926,29 @@ virtualenv = ">=20.10.0" [[package]] name = "pycountry" -version = "23.12.11" +version = "24.6.1" description = "ISO country, subdivision, language, currency and script definitions and their translations" optional = false python-versions = ">=3.8" files = [ - {file = "pycountry-23.12.11-py3-none-any.whl", hash = "sha256:2ff91cff4f40ff61086e773d61e72005fe95de4a57bfc765509db05695dc50ab"}, - {file = "pycountry-23.12.11.tar.gz", hash = "sha256:00569d82eaefbc6a490a311bfa84a9c571cff9ddbf8b0a4f4e7b4f868b4ad925"}, + {file = "pycountry-24.6.1-py3-none-any.whl", hash = "sha256:f1a4fb391cd7214f8eefd39556d740adcc233c778a27f8942c8dca351d6ce06f"}, + {file = "pycountry-24.6.1.tar.gz", hash = "sha256:b61b3faccea67f87d10c1f2b0fc0be714409e8fcdcc1315613174f6466c10221"}, ] [[package]] name = "pydantic" -version = "2.8.0" +version = "2.8.2" description = "Data validation using Python type hints" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic-2.8.0-py3-none-any.whl", hash = "sha256:ead4f3a1e92386a734ca1411cb25d94147cf8778ed5be6b56749047676d6364e"}, - {file = "pydantic-2.8.0.tar.gz", hash = "sha256:d970ffb9d030b710795878940bd0489842c638e7252fc4a19c3ae2f7da4d6141"}, + {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.20.0" +pydantic-core = "2.20.1" typing-extensions = [ {version = ">=4.12.2", markers = "python_version >= \"3.13\""}, {version = ">=4.6.1", markers = "python_version < \"3.13\""}, @@ -945,99 +959,100 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.20.0" +version = "2.20.1" description = "Core functionality for Pydantic validation and serialization" optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.20.0-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:e9dcd7fb34f7bfb239b5fa420033642fff0ad676b765559c3737b91f664d4fa9"}, - {file = "pydantic_core-2.20.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:649a764d9b0da29816889424697b2a3746963ad36d3e0968784ceed6e40c6355"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7701df088d0b05f3460f7ba15aec81ac8b0fb5690367dfd072a6c38cf5b7fdb5"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ab760f17c3e792225cdaef31ca23c0aea45c14ce80d8eff62503f86a5ab76bff"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:cb1ad5b4d73cde784cf64580166568074f5ccd2548d765e690546cff3d80937d"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b81ec2efc04fc1dbf400647d4357d64fb25543bae38d2d19787d69360aad21c9"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4a9732a5cad764ba37f3aa873dccb41b584f69c347a57323eda0930deec8e10"}, - {file = "pydantic_core-2.20.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6dc85b9e10cc21d9c1055f15684f76fa4facadddcb6cd63abab702eb93c98943"}, - {file = "pydantic_core-2.20.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:21d9f7e24f63fdc7118e6cc49defaab8c1d27570782f7e5256169d77498cf7c7"}, - {file = "pydantic_core-2.20.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8b315685832ab9287e6124b5d74fc12dda31e6421d7f6b08525791452844bc2d"}, - {file = "pydantic_core-2.20.0-cp310-none-win32.whl", hash = "sha256:c3dc8ec8b87c7ad534c75b8855168a08a7036fdb9deeeed5705ba9410721c84d"}, - {file = "pydantic_core-2.20.0-cp310-none-win_amd64.whl", hash = "sha256:85770b4b37bb36ef93a6122601795231225641003e0318d23c6233c59b424279"}, - {file = "pydantic_core-2.20.0-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:58e251bb5a5998f7226dc90b0b753eeffa720bd66664eba51927c2a7a2d5f32c"}, - {file = "pydantic_core-2.20.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:78d584caac52c24240ef9ecd75de64c760bbd0e20dbf6973631815e3ef16ef8b"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5084ec9721f82bef5ff7c4d1ee65e1626783abb585f8c0993833490b63fe1792"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:6d0f52684868db7c218437d260e14d37948b094493f2646f22d3dda7229bbe3f"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:1def125d59a87fe451212a72ab9ed34c118ff771e5473fef4f2f95d8ede26d75"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b34480fd6778ab356abf1e9086a4ced95002a1e195e8d2fd182b0def9d944d11"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d42669d319db366cb567c3b444f43caa7ffb779bf9530692c6f244fc635a41eb"}, - {file = "pydantic_core-2.20.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:53b06aea7a48919a254b32107647be9128c066aaa6ee6d5d08222325f25ef175"}, - {file = "pydantic_core-2.20.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:1f038156b696a1c39d763b2080aeefa87ddb4162c10aa9fabfefffc3dd8180fa"}, - {file = "pydantic_core-2.20.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:3f0f3a4a23717280a5ee3ac4fb1f81d6fde604c9ec5100f7f6f987716bb8c137"}, - {file = "pydantic_core-2.20.0-cp311-none-win32.whl", hash = "sha256:316fe7c3fec017affd916a0c83d6f1ec697cbbbdf1124769fa73328e7907cc2e"}, - {file = "pydantic_core-2.20.0-cp311-none-win_amd64.whl", hash = "sha256:2d06a7fa437f93782e3f32d739c3ec189f82fca74336c08255f9e20cea1ed378"}, - {file = "pydantic_core-2.20.0-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:d6f8c49657f3eb7720ed4c9b26624063da14937fc94d1812f1e04a2204db3e17"}, - {file = "pydantic_core-2.20.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ad1bd2f377f56fec11d5cfd0977c30061cd19f4fa199bf138b200ec0d5e27eeb"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ed741183719a5271f97d93bbcc45ed64619fa38068aaa6e90027d1d17e30dc8d"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d82e5ed3a05f2dcb89c6ead2fd0dbff7ac09bc02c1b4028ece2d3a3854d049ce"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b2ba34a099576234671f2e4274e5bc6813b22e28778c216d680eabd0db3f7dad"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:879ae6bb08a063b3e1b7ac8c860096d8fd6b48dd9b2690b7f2738b8c835e744b"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0b0eefc7633a04c0694340aad91fbfd1986fe1a1e0c63a22793ba40a18fcbdc8"}, - {file = "pydantic_core-2.20.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:73deadd6fd8a23e2f40b412b3ac617a112143c8989a4fe265050fd91ba5c0608"}, - {file = "pydantic_core-2.20.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:35681445dc85446fb105943d81ae7569aa7e89de80d1ca4ac3229e05c311bdb1"}, - {file = "pydantic_core-2.20.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:0f6dd3612a3b9f91f2e63924ea18a4476656c6d01843ca20a4c09e00422195af"}, - {file = "pydantic_core-2.20.0-cp312-none-win32.whl", hash = "sha256:7e37b6bb6e90c2b8412b06373c6978d9d81e7199a40e24a6ef480e8acdeaf918"}, - {file = "pydantic_core-2.20.0-cp312-none-win_amd64.whl", hash = "sha256:7d4df13d1c55e84351fab51383520b84f490740a9f1fec905362aa64590b7a5d"}, - {file = "pydantic_core-2.20.0-cp313-cp313-macosx_10_12_x86_64.whl", hash = "sha256:d43e7ab3b65e4dc35a7612cfff7b0fd62dce5bc11a7cd198310b57f39847fd6c"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7b6a24d7b5893392f2b8e3b7a0031ae3b14c6c1942a4615f0d8794fdeeefb08b"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:b2f13c3e955a087c3ec86f97661d9f72a76e221281b2262956af381224cfc243"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:72432fd6e868c8d0a6849869e004b8bcae233a3c56383954c228316694920b38"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d70a8ff2d4953afb4cbe6211f17268ad29c0b47e73d3372f40e7775904bc28fc"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8e49524917b8d3c2f42cd0d2df61178e08e50f5f029f9af1f402b3ee64574392"}, - {file = "pydantic_core-2.20.0-cp313-cp313-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a4f0f71653b1c1bad0350bc0b4cc057ab87b438ff18fa6392533811ebd01439c"}, - {file = "pydantic_core-2.20.0-cp313-cp313-musllinux_1_1_aarch64.whl", hash = "sha256:16197e6f4fdecb9892ed2436e507e44f0a1aa2cff3b9306d1c879ea2f9200997"}, - {file = "pydantic_core-2.20.0-cp313-cp313-musllinux_1_1_x86_64.whl", hash = "sha256:763602504bf640b3ded3bba3f8ed8a1cc2fc6a87b8d55c1c5689f428c49c947e"}, - {file = "pydantic_core-2.20.0-cp313-none-win32.whl", hash = "sha256:a3f243f318bd9523277fa123b3163f4c005a3e8619d4b867064de02f287a564d"}, - {file = "pydantic_core-2.20.0-cp313-none-win_amd64.whl", hash = "sha256:03aceaf6a5adaad3bec2233edc5a7905026553916615888e53154807e404545c"}, - {file = "pydantic_core-2.20.0-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:d6f2d8b8da1f03f577243b07bbdd3412eee3d37d1f2fd71d1513cbc76a8c1239"}, - {file = "pydantic_core-2.20.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a272785a226869416c6b3c1b7e450506152d3844207331f02f27173562c917e0"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:efbb412d55a4ffe73963fed95c09ccb83647ec63b711c4b3752be10a56f0090b"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:1e4f46189d8740561b43655263a41aac75ff0388febcb2c9ec4f1b60a0ec12f3"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:87d3df115f4a3c8c5e4d5acf067d399c6466d7e604fc9ee9acbe6f0c88a0c3cf"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:a340d2bdebe819d08f605e9705ed551c3feb97e4fd71822d7147c1e4bdbb9508"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:616b9c2f882393d422ba11b40e72382fe975e806ad693095e9a3b67c59ea6150"}, - {file = "pydantic_core-2.20.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:25c46bb2ff6084859bbcfdf4f1a63004b98e88b6d04053e8bf324e115398e9e7"}, - {file = "pydantic_core-2.20.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:23425eccef8f2c342f78d3a238c824623836c6c874d93c726673dbf7e56c78c0"}, - {file = "pydantic_core-2.20.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:52527e8f223ba29608d999d65b204676398009725007c9336651c2ec2d93cffc"}, - {file = "pydantic_core-2.20.0-cp38-none-win32.whl", hash = "sha256:1c3c5b7f70dd19a6845292b0775295ea81c61540f68671ae06bfe4421b3222c2"}, - {file = "pydantic_core-2.20.0-cp38-none-win_amd64.whl", hash = "sha256:8093473d7b9e908af1cef30025609afc8f5fd2a16ff07f97440fd911421e4432"}, - {file = "pydantic_core-2.20.0-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:ee7785938e407418795e4399b2bf5b5f3cf6cf728077a7f26973220d58d885cf"}, - {file = "pydantic_core-2.20.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:0e75794883d635071cf6b4ed2a5d7a1e50672ab7a051454c76446ef1ebcdcc91"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:344e352c96e53b4f56b53d24728217c69399b8129c16789f70236083c6ceb2ac"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:978d4123ad1e605daf1ba5e01d4f235bcf7b6e340ef07e7122e8e9cfe3eb61ab"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:3c05eaf6c863781eb834ab41f5963604ab92855822a2062897958089d1335dad"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bc7e43b4a528ffca8c9151b6a2ca34482c2fdc05e6aa24a84b7f475c896fc51d"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:658287a29351166510ebbe0a75c373600cc4367a3d9337b964dada8d38bcc0f4"}, - {file = "pydantic_core-2.20.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:1dacf660d6de692fe351e8c806e7efccf09ee5184865893afbe8e59be4920b4a"}, - {file = "pydantic_core-2.20.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3e147fc6e27b9a487320d78515c5f29798b539179f7777018cedf51b7749e4f4"}, - {file = "pydantic_core-2.20.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:c867230d715a3dd1d962c8d9bef0d3168994ed663e21bf748b6e3a529a129aab"}, - {file = "pydantic_core-2.20.0-cp39-none-win32.whl", hash = "sha256:22b813baf0dbf612752d8143a2dbf8e33ccb850656b7850e009bad2e101fc377"}, - {file = "pydantic_core-2.20.0-cp39-none-win_amd64.whl", hash = "sha256:3a7235b46c1bbe201f09b6f0f5e6c36b16bad3d0532a10493742f91fbdc8035f"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:cafde15a6f7feaec2f570646e2ffc5b73412295d29134a29067e70740ec6ee20"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:2aec8eeea0b08fd6bc2213d8e86811a07491849fd3d79955b62d83e32fa2ad5f"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:840200827984f1c4e114008abc2f5ede362d6e11ed0b5931681884dd41852ff1"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f8ea1d8b7df522e5ced34993c423c3bf3735c53df8b2a15688a2f03a7d678800"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5b8376a867047bf08910573deb95d3c8dfb976eb014ee24f3b5a61ccc5bee1b"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:d08264b4460326cefacc179fc1411304d5af388a79910832835e6f641512358b"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:7a3639011c2e8a9628466f616ed7fb413f30032b891898e10895a0a8b5857d6c"}, - {file = "pydantic_core-2.20.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:05e83ce2f7eba29e627dd8066aa6c4c0269b2d4f889c0eba157233a353053cea"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:603a843fea76a595c8f661cd4da4d2281dff1e38c4a836a928eac1a2f8fe88e4"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ac76f30d5d3454f4c28826d891fe74d25121a346c69523c9810ebba43f3b1cec"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:22e3b1d4b1b3f6082849f9b28427ef147a5b46a6132a3dbaf9ca1baa40c88609"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2761f71faed820e25ec62eacba670d1b5c2709bb131a19fcdbfbb09884593e5a"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a0586cddbf4380e24569b8a05f234e7305717cc8323f50114dfb2051fcbce2a3"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:b8c46a8cf53e849eea7090f331ae2202cd0f1ceb090b00f5902c423bd1e11805"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:b4a085bd04af7245e140d1b95619fe8abb445a3d7fdf219b3f80c940853268ef"}, - {file = "pydantic_core-2.20.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:116b326ac82c8b315e7348390f6d30bcfe6e688a7d3f1de50ff7bcc2042a23c2"}, - {file = "pydantic_core-2.20.0.tar.gz", hash = "sha256:366be8e64e0cb63d87cf79b4e1765c0703dd6313c729b22e7b9e378db6b96877"}, + {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] @@ -1045,45 +1060,49 @@ typing-extensions = ">=4.6.0,<4.7.0 || >4.7.0" [[package]] name = "pydantic-extra-types" -version = "2.7.0" +version = "2.9.0" description = "Extra Pydantic types." optional = false python-versions = ">=3.8" files = [ - {file = "pydantic_extra_types-2.7.0-py3-none-any.whl", hash = "sha256:ac01bbdaa4f85e4c4744a9792c5b0cfe61efa5028a0e670c3d8bfbf8b36c8543"}, - {file = "pydantic_extra_types-2.7.0.tar.gz", hash = "sha256:b9d9ddd755fa5960ec5a77cffcbd5d8796a0116e1dfc8f7c3a27fa0041693382"}, + {file = "pydantic_extra_types-2.9.0-py3-none-any.whl", hash = "sha256:f0bb975508572ba7bf3390b7337807588463b7248587e69f43b1ad7c797530d0"}, + {file = "pydantic_extra_types-2.9.0.tar.gz", hash = "sha256:e061c01636188743bb69f368dcd391f327b8cfbfede2fe1cbb1211b06601ba3b"}, ] [package.dependencies] pydantic = ">=2.5.2" [package.extras] -all = ["pendulum (>=3.0.0,<4.0.0)", "phonenumbers (>=8,<9)", "pycountry (>=23)", "python-ulid (>=1,<2)", "python-ulid (>=1,<3)"] +all = ["pendulum (>=3.0.0,<4.0.0)", "phonenumbers (>=8,<9)", "pycountry (>=23)", "python-ulid (>=1,<2)", "python-ulid (>=1,<3)", "pytz (>=2024.1)", "semver (>=3.0.2)", "tzdata (>=2024.1)"] +pendulum = ["pendulum (>=3.0.0,<4.0.0)"] +phonenumbers = ["phonenumbers (>=8,<9)"] +pycountry = ["pycountry (>=23)"] +python-ulid = ["python-ulid (>=1,<2)", "python-ulid (>=1,<3)"] +semver = ["semver (>=3.0.2)"] [[package]] name = "pygments" -version = "2.17.2" +version = "2.18.0" description = "Pygments is a syntax highlighting package written in Python." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pygments-2.17.2-py3-none-any.whl", hash = "sha256:b27c2826c47d0f3219f29554824c30c5e8945175d888647acd804ddd04af846c"}, - {file = "pygments-2.17.2.tar.gz", hash = "sha256:da46cec9fd2de5be3a8a784f434e4c4ab670b4ff54d605c4c2717e9d49c4c367"}, + {file = "pygments-2.18.0-py3-none-any.whl", hash = "sha256:b8e6aca0523f3ab76fee51799c488e38782ac06eafcf95e7ba832985c8e7b13a"}, + {file = "pygments-2.18.0.tar.gz", hash = "sha256:786ff802f32e91311bff3889f6e9a86e81505fe99f2735bb6d60ae0c5004f199"}, ] [package.extras] -plugins = ["importlib-metadata"] windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pymdown-extensions" -version = "10.8" +version = "10.8.1" description = "Extension pack for Python Markdown." optional = false python-versions = ">=3.8" files = [ - {file = "pymdown_extensions-10.8-py3-none-any.whl", hash = "sha256:3539003ff0d5e219ba979d2dc961d18fcad5ac259e66c764482e8347b4c0503c"}, - {file = "pymdown_extensions-10.8.tar.gz", hash = "sha256:91ca336caf414e1e5e0626feca86e145de9f85a3921a7bcbd32890b51738c428"}, + {file = "pymdown_extensions-10.8.1-py3-none-any.whl", hash = "sha256:f938326115884f48c6059c67377c46cf631c733ef3629b6eed1349989d1b30cb"}, + {file = "pymdown_extensions-10.8.1.tar.gz", hash = "sha256:3ab1db5c9e21728dabf75192d71471f8e50f216627e9a1fa9535ecb0231b9940"}, ] [package.dependencies] @@ -1095,13 +1114,13 @@ extra = ["pygments (>=2.12)"] [[package]] name = "pytest" -version = "8.1.1" +version = "8.2.2" description = "pytest: simple powerful testing with Python" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-8.1.1-py3-none-any.whl", hash = "sha256:2a8386cfc11fa9d2c50ee7b2a57e7d898ef90470a7a34c4b949ff59662bb78b7"}, - {file = "pytest-8.1.1.tar.gz", hash = "sha256:ac978141a75948948817d360297b7aae0fcb9d6ff6bc9ec6d514b85d5a65c044"}, + {file = "pytest-8.2.2-py3-none-any.whl", hash = "sha256:c434598117762e2bd304e526244f67bf66bbd7b5d6cf22138be51ff661980343"}, + {file = "pytest-8.2.2.tar.gz", hash = "sha256:de4bb8104e201939ccdc688b27a89a7be2079b22e2bd2b07f806b6ba71117977"}, ] [package.dependencies] @@ -1109,21 +1128,21 @@ colorama = {version = "*", markers = "sys_platform == \"win32\""} exceptiongroup = {version = ">=1.0.0rc8", markers = "python_version < \"3.11\""} iniconfig = "*" packaging = "*" -pluggy = ">=1.4,<2.0" +pluggy = ">=1.5,<2.0" tomli = {version = ">=1", markers = "python_version < \"3.11\""} [package.extras] -testing = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] +dev = ["argcomplete", "attrs (>=19.2)", "hypothesis (>=3.56)", "mock", "pygments (>=2.7.2)", "requests", "setuptools", "xmlschema"] [[package]] name = "pytest-asyncio" -version = "0.23.6" +version = "0.23.7" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.6.tar.gz", hash = "sha256:ffe523a89c1c222598c76856e76852b787504ddb72dd5d9b6617ffa8aa2cde5f"}, - {file = "pytest_asyncio-0.23.6-py3-none-any.whl", hash = "sha256:68516fdd1018ac57b846c9846b954f0393b26f094764a28c955eabb0536a4e8a"}, + {file = "pytest_asyncio-0.23.7-py3-none-any.whl", hash = "sha256:009b48127fbe44518a547bddd25611551b0e43ccdbf1e67d12479f569832c20b"}, + {file = "pytest_asyncio-0.23.7.tar.gz", hash = "sha256:5f5c72948f4c49e7db4f29f2521d4031f1c27f86e57b046126654083d4770268"}, ] [package.dependencies] @@ -1223,115 +1242,101 @@ pyyaml = "*" [[package]] name = "regex" -version = "2024.4.16" +version = "2024.5.15" description = "Alternative regular expression module, to replace re." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:fb83cc090eac63c006871fd24db5e30a1f282faa46328572661c0a24a2323a08"}, - {file = "regex-2024.4.16-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8c91e1763696c0eb66340c4df98623c2d4e77d0746b8f8f2bee2c6883fd1fe18"}, - {file = "regex-2024.4.16-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:10188fe732dec829c7acca7422cdd1bf57d853c7199d5a9e96bb4d40db239c73"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:956b58d692f235cfbf5b4f3abd6d99bf102f161ccfe20d2fd0904f51c72c4c66"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a70b51f55fd954d1f194271695821dd62054d949efd6368d8be64edd37f55c86"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:5c02fcd2bf45162280613d2e4a1ca3ac558ff921ae4e308ecb307650d3a6ee51"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c4ed75ea6892a56896d78f11006161eea52c45a14994794bcfa1654430984b22"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bd727ad276bb91928879f3aa6396c9a1d34e5e180dce40578421a691eeb77f47"}, - {file = "regex-2024.4.16-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:7cbc5d9e8a1781e7be17da67b92580d6ce4dcef5819c1b1b89f49d9678cc278c"}, - {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:78fddb22b9ef810b63ef341c9fcf6455232d97cfe03938cbc29e2672c436670e"}, - {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:445ca8d3c5a01309633a0c9db57150312a181146315693273e35d936472df912"}, - {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:95399831a206211d6bc40224af1c635cb8790ddd5c7493e0bd03b85711076a53"}, - {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:7731728b6568fc286d86745f27f07266de49603a6fdc4d19c87e8c247be452af"}, - {file = "regex-2024.4.16-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:4facc913e10bdba42ec0aee76d029aedda628161a7ce4116b16680a0413f658a"}, - {file = "regex-2024.4.16-cp310-cp310-win32.whl", hash = "sha256:911742856ce98d879acbea33fcc03c1d8dc1106234c5e7d068932c945db209c0"}, - {file = "regex-2024.4.16-cp310-cp310-win_amd64.whl", hash = "sha256:e0a2df336d1135a0b3a67f3bbf78a75f69562c1199ed9935372b82215cddd6e2"}, - {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:1210365faba7c2150451eb78ec5687871c796b0f1fa701bfd2a4a25420482d26"}, - {file = "regex-2024.4.16-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:9ab40412f8cd6f615bfedea40c8bf0407d41bf83b96f6fc9ff34976d6b7037fd"}, - {file = "regex-2024.4.16-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:fd80d1280d473500d8086d104962a82d77bfbf2b118053824b7be28cd5a79ea5"}, - {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bb966fdd9217e53abf824f437a5a2d643a38d4fd5fd0ca711b9da683d452969"}, - {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:20b7a68444f536365af42a75ccecb7ab41a896a04acf58432db9e206f4e525d6"}, - {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b74586dd0b039c62416034f811d7ee62810174bb70dffcca6439f5236249eb09"}, - {file = "regex-2024.4.16-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0c8290b44d8b0af4e77048646c10c6e3aa583c1ca67f3b5ffb6e06cf0c6f0f89"}, - {file = "regex-2024.4.16-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2d80a6749724b37853ece57988b39c4e79d2b5fe2869a86e8aeae3bbeef9eb0"}, - {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:3a1018e97aeb24e4f939afcd88211ace472ba566efc5bdf53fd8fd7f41fa7170"}, - {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8d015604ee6204e76569d2f44e5a210728fa917115bef0d102f4107e622b08d5"}, - {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:3d5ac5234fb5053850d79dd8eb1015cb0d7d9ed951fa37aa9e6249a19aa4f336"}, - {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:0a38d151e2cdd66d16dab550c22f9521ba79761423b87c01dae0a6e9add79c0d"}, - {file = "regex-2024.4.16-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:159dc4e59a159cb8e4e8f8961eb1fa5d58f93cb1acd1701d8aff38d45e1a84a6"}, - {file = "regex-2024.4.16-cp311-cp311-win32.whl", hash = "sha256:ba2336d6548dee3117520545cfe44dc28a250aa091f8281d28804aa8d707d93d"}, - {file = "regex-2024.4.16-cp311-cp311-win_amd64.whl", hash = "sha256:8f83b6fd3dc3ba94d2b22717f9c8b8512354fd95221ac661784df2769ea9bba9"}, - {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:80b696e8972b81edf0af2a259e1b2a4a661f818fae22e5fa4fa1a995fb4a40fd"}, - {file = "regex-2024.4.16-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:d61ae114d2a2311f61d90c2ef1358518e8f05eafda76eaf9c772a077e0b465ec"}, - {file = "regex-2024.4.16-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:8ba6745440b9a27336443b0c285d705ce73adb9ec90e2f2004c64d95ab5a7598"}, - {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6295004b2dd37b0835ea5c14a33e00e8cfa3c4add4d587b77287825f3418d310"}, - {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4aba818dcc7263852aabb172ec27b71d2abca02a593b95fa79351b2774eb1d2b"}, - {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d0800631e565c47520aaa04ae38b96abc5196fe8b4aa9bd864445bd2b5848a7a"}, - {file = "regex-2024.4.16-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:08dea89f859c3df48a440dbdcd7b7155bc675f2fa2ec8c521d02dc69e877db70"}, - {file = "regex-2024.4.16-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:eeaa0b5328b785abc344acc6241cffde50dc394a0644a968add75fcefe15b9d4"}, - {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:4e819a806420bc010489f4e741b3036071aba209f2e0989d4750b08b12a9343f"}, - {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:c2d0e7cbb6341e830adcbfa2479fdeebbfbb328f11edd6b5675674e7a1e37730"}, - {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:91797b98f5e34b6a49f54be33f72e2fb658018ae532be2f79f7c63b4ae225145"}, - {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:d2da13568eff02b30fd54fccd1e042a70fe920d816616fda4bf54ec705668d81"}, - {file = "regex-2024.4.16-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:370c68dc5570b394cbaadff50e64d705f64debed30573e5c313c360689b6aadc"}, - {file = "regex-2024.4.16-cp312-cp312-win32.whl", hash = "sha256:904c883cf10a975b02ab3478bce652f0f5346a2c28d0a8521d97bb23c323cc8b"}, - {file = "regex-2024.4.16-cp312-cp312-win_amd64.whl", hash = "sha256:785c071c982dce54d44ea0b79cd6dfafddeccdd98cfa5f7b86ef69b381b457d9"}, - {file = "regex-2024.4.16-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:e2f142b45c6fed48166faeb4303b4b58c9fcd827da63f4cf0a123c3480ae11fb"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e87ab229332ceb127a165612d839ab87795972102cb9830e5f12b8c9a5c1b508"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:81500ed5af2090b4a9157a59dbc89873a25c33db1bb9a8cf123837dcc9765047"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b340cccad138ecb363324aa26893963dcabb02bb25e440ebdf42e30963f1a4e0"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2c72608e70f053643437bd2be0608f7f1c46d4022e4104d76826f0839199347a"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a01fe2305e6232ef3e8f40bfc0f0f3a04def9aab514910fa4203bafbc0bb4682"}, - {file = "regex-2024.4.16-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:03576e3a423d19dda13e55598f0fd507b5d660d42c51b02df4e0d97824fdcae3"}, - {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:549c3584993772e25f02d0656ac48abdda73169fe347263948cf2b1cead622f3"}, - {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:34422d5a69a60b7e9a07a690094e824b66f5ddc662a5fc600d65b7c174a05f04"}, - {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:5f580c651a72b75c39e311343fe6875d6f58cf51c471a97f15a938d9fe4e0d37"}, - {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:3399dd8a7495bbb2bacd59b84840eef9057826c664472e86c91d675d007137f5"}, - {file = "regex-2024.4.16-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:8d1f86f3f4e2388aa3310b50694ac44daefbd1681def26b4519bd050a398dc5a"}, - {file = "regex-2024.4.16-cp37-cp37m-win32.whl", hash = "sha256:dd5acc0a7d38fdc7a3a6fd3ad14c880819008ecb3379626e56b163165162cc46"}, - {file = "regex-2024.4.16-cp37-cp37m-win_amd64.whl", hash = "sha256:ba8122e3bb94ecda29a8de4cf889f600171424ea586847aa92c334772d200331"}, - {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:743deffdf3b3481da32e8a96887e2aa945ec6685af1cfe2bcc292638c9ba2f48"}, - {file = "regex-2024.4.16-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7571f19f4a3fd00af9341c7801d1ad1967fc9c3f5e62402683047e7166b9f2b4"}, - {file = "regex-2024.4.16-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:df79012ebf6f4efb8d307b1328226aef24ca446b3ff8d0e30202d7ebcb977a8c"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e757d475953269fbf4b441207bb7dbdd1c43180711b6208e129b637792ac0b93"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:4313ab9bf6a81206c8ac28fdfcddc0435299dc88cad12cc6305fd0e78b81f9e4"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d83c2bc678453646f1a18f8db1e927a2d3f4935031b9ad8a76e56760461105dd"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9df1bfef97db938469ef0a7354b2d591a2d438bc497b2c489471bec0e6baf7c4"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62120ed0de69b3649cc68e2965376048793f466c5a6c4370fb27c16c1beac22d"}, - {file = "regex-2024.4.16-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:c2ef6f7990b6e8758fe48ad08f7e2f66c8f11dc66e24093304b87cae9037bb4a"}, - {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:8fc6976a3395fe4d1fbeb984adaa8ec652a1e12f36b56ec8c236e5117b585427"}, - {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:03e68f44340528111067cecf12721c3df4811c67268b897fbe695c95f860ac42"}, - {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:ec7e0043b91115f427998febaa2beb82c82df708168b35ece3accb610b91fac1"}, - {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:c21fc21a4c7480479d12fd8e679b699f744f76bb05f53a1d14182b31f55aac76"}, - {file = "regex-2024.4.16-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:12f6a3f2f58bb7344751919a1876ee1b976fe08b9ffccb4bbea66f26af6017b9"}, - {file = "regex-2024.4.16-cp38-cp38-win32.whl", hash = "sha256:479595a4fbe9ed8f8f72c59717e8cf222da2e4c07b6ae5b65411e6302af9708e"}, - {file = "regex-2024.4.16-cp38-cp38-win_amd64.whl", hash = "sha256:0534b034fba6101611968fae8e856c1698da97ce2efb5c2b895fc8b9e23a5834"}, - {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:a7ccdd1c4a3472a7533b0a7aa9ee34c9a2bef859ba86deec07aff2ad7e0c3b94"}, - {file = "regex-2024.4.16-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:6f2f017c5be19984fbbf55f8af6caba25e62c71293213f044da3ada7091a4455"}, - {file = "regex-2024.4.16-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:803b8905b52de78b173d3c1e83df0efb929621e7b7c5766c0843704d5332682f"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:684008ec44ad275832a5a152f6e764bbe1914bea10968017b6feaecdad5736e0"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:65436dce9fdc0aeeb0a0effe0839cb3d6a05f45aa45a4d9f9c60989beca78b9c"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ea355eb43b11764cf799dda62c658c4d2fdb16af41f59bb1ccfec517b60bcb07"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:98c1165f3809ce7774f05cb74e5408cd3aa93ee8573ae959a97a53db3ca3180d"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cccc79a9be9b64c881f18305a7c715ba199e471a3973faeb7ba84172abb3f317"}, - {file = "regex-2024.4.16-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:00169caa125f35d1bca6045d65a662af0202704489fada95346cfa092ec23f39"}, - {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:6cc38067209354e16c5609b66285af17a2863a47585bcf75285cab33d4c3b8df"}, - {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:23cff1b267038501b179ccbbd74a821ac4a7192a1852d1d558e562b507d46013"}, - {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:b9d320b3bf82a39f248769fc7f188e00f93526cc0fe739cfa197868633d44701"}, - {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:89ec7f2c08937421bbbb8b48c54096fa4f88347946d4747021ad85f1b3021b3c"}, - {file = "regex-2024.4.16-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:4918fd5f8b43aa7ec031e0fef1ee02deb80b6afd49c85f0790be1dc4ce34cb50"}, - {file = "regex-2024.4.16-cp39-cp39-win32.whl", hash = "sha256:684e52023aec43bdf0250e843e1fdd6febbe831bd9d52da72333fa201aaa2335"}, - {file = "regex-2024.4.16-cp39-cp39-win_amd64.whl", hash = "sha256:e697e1c0238133589e00c244a8b676bc2cfc3ab4961318d902040d099fec7483"}, - {file = "regex-2024.4.16.tar.gz", hash = "sha256:fa454d26f2e87ad661c4f0c5a5fe4cf6aab1e307d1b94f16ffdfcb089ba685c0"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:a81e3cfbae20378d75185171587cbf756015ccb14840702944f014e0d93ea09f"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:7b59138b219ffa8979013be7bc85bb60c6f7b7575df3d56dc1e403a438c7a3f6"}, + {file = "regex-2024.5.15-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:a0bd000c6e266927cb7a1bc39d55be95c4b4f65c5be53e659537537e019232b1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5eaa7ddaf517aa095fa8da0b5015c44d03da83f5bd49c87961e3c997daed0de7"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ba68168daedb2c0bab7fd7e00ced5ba90aebf91024dea3c88ad5063c2a562cca"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6e8d717bca3a6e2064fc3a08df5cbe366369f4b052dcd21b7416e6d71620dca1"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1337b7dbef9b2f71121cdbf1e97e40de33ff114801263b275aafd75303bd62b5"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9ebd0a36102fcad2f03696e8af4ae682793a5d30b46c647eaf280d6cfb32796"}, + {file = "regex-2024.5.15-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:9efa1a32ad3a3ea112224897cdaeb6aa00381627f567179c0314f7b65d354c62"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_aarch64.whl", hash = "sha256:1595f2d10dff3d805e054ebdc41c124753631b6a471b976963c7b28543cf13b0"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_i686.whl", hash = "sha256:b802512f3e1f480f41ab5f2cfc0e2f761f08a1f41092d6718868082fc0d27143"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_ppc64le.whl", hash = "sha256:a0981022dccabca811e8171f913de05720590c915b033b7e601f35ce4ea7019f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_s390x.whl", hash = "sha256:19068a6a79cf99a19ccefa44610491e9ca02c2be3305c7760d3831d38a467a6f"}, + {file = "regex-2024.5.15-cp310-cp310-musllinux_1_2_x86_64.whl", hash = "sha256:1b5269484f6126eee5e687785e83c6b60aad7663dafe842b34691157e5083e53"}, + {file = "regex-2024.5.15-cp310-cp310-win32.whl", hash = "sha256:ada150c5adfa8fbcbf321c30c751dc67d2f12f15bd183ffe4ec7cde351d945b3"}, + {file = "regex-2024.5.15-cp310-cp310-win_amd64.whl", hash = "sha256:ac394ff680fc46b97487941f5e6ae49a9f30ea41c6c6804832063f14b2a5a145"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f5b1dff3ad008dccf18e652283f5e5339d70bf8ba7c98bf848ac33db10f7bc7a"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6a2b494a76983df8e3d3feea9b9ffdd558b247e60b92f877f93a1ff43d26656"}, + {file = "regex-2024.5.15-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:a32b96f15c8ab2e7d27655969a23895eb799de3665fa94349f3b2fbfd547236f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:10002e86e6068d9e1c91eae8295ef690f02f913c57db120b58fdd35a6bb1af35"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ec54d5afa89c19c6dd8541a133be51ee1017a38b412b1321ccb8d6ddbeb4cf7d"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:10e4ce0dca9ae7a66e6089bb29355d4432caed736acae36fef0fdd7879f0b0cb"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3e507ff1e74373c4d3038195fdd2af30d297b4f0950eeda6f515ae3d84a1770f"}, + {file = "regex-2024.5.15-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d1f059a4d795e646e1c37665b9d06062c62d0e8cc3c511fe01315973a6542e40"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_aarch64.whl", hash = "sha256:0721931ad5fe0dda45d07f9820b90b2148ccdd8e45bb9e9b42a146cb4f695649"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_i686.whl", hash = "sha256:833616ddc75ad595dee848ad984d067f2f31be645d603e4d158bba656bbf516c"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_ppc64le.whl", hash = "sha256:287eb7f54fc81546346207c533ad3c2c51a8d61075127d7f6d79aaf96cdee890"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_s390x.whl", hash = "sha256:19dfb1c504781a136a80ecd1fff9f16dddf5bb43cec6871778c8a907a085bb3d"}, + {file = "regex-2024.5.15-cp311-cp311-musllinux_1_2_x86_64.whl", hash = "sha256:119af6e56dce35e8dfb5222573b50c89e5508d94d55713c75126b753f834de68"}, + {file = "regex-2024.5.15-cp311-cp311-win32.whl", hash = "sha256:1c1c174d6ec38d6c8a7504087358ce9213d4332f6293a94fbf5249992ba54efa"}, + {file = "regex-2024.5.15-cp311-cp311-win_amd64.whl", hash = "sha256:9e717956dcfd656f5055cc70996ee2cc82ac5149517fc8e1b60261b907740201"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:632b01153e5248c134007209b5c6348a544ce96c46005d8456de1d552455b014"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:e64198f6b856d48192bf921421fdd8ad8eb35e179086e99e99f711957ffedd6e"}, + {file = "regex-2024.5.15-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:68811ab14087b2f6e0fc0c2bae9ad689ea3584cad6917fc57be6a48bbd012c49"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f8ec0c2fea1e886a19c3bee0cd19d862b3aa75dcdfb42ebe8ed30708df64687a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d0c0c0003c10f54a591d220997dd27d953cd9ccc1a7294b40a4be5312be8797b"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2431b9e263af1953c55abbd3e2efca67ca80a3de8a0437cb58e2421f8184717a"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4a605586358893b483976cffc1723fb0f83e526e8f14c6e6614e75919d9862cf"}, + {file = "regex-2024.5.15-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:391d7f7f1e409d192dba8bcd42d3e4cf9e598f3979cdaed6ab11288da88cb9f2"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_aarch64.whl", hash = "sha256:9ff11639a8d98969c863d4617595eb5425fd12f7c5ef6621a4b74b71ed8726d5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_i686.whl", hash = "sha256:4eee78a04e6c67e8391edd4dad3279828dd66ac4b79570ec998e2155d2e59fd5"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_ppc64le.whl", hash = "sha256:8fe45aa3f4aa57faabbc9cb46a93363edd6197cbc43523daea044e9ff2fea83e"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_s390x.whl", hash = "sha256:d0a3d8d6acf0c78a1fff0e210d224b821081330b8524e3e2bc5a68ef6ab5803d"}, + {file = "regex-2024.5.15-cp312-cp312-musllinux_1_2_x86_64.whl", hash = "sha256:c486b4106066d502495b3025a0a7251bf37ea9540433940a23419461ab9f2a80"}, + {file = "regex-2024.5.15-cp312-cp312-win32.whl", hash = "sha256:c49e15eac7c149f3670b3e27f1f28a2c1ddeccd3a2812cba953e01be2ab9b5fe"}, + {file = "regex-2024.5.15-cp312-cp312-win_amd64.whl", hash = "sha256:673b5a6da4557b975c6c90198588181029c60793835ce02f497ea817ff647cb2"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:87e2a9c29e672fc65523fb47a90d429b70ef72b901b4e4b1bd42387caf0d6835"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:c3bea0ba8b73b71b37ac833a7f3fd53825924165da6a924aec78c13032f20850"}, + {file = "regex-2024.5.15-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:bfc4f82cabe54f1e7f206fd3d30fda143f84a63fe7d64a81558d6e5f2e5aaba9"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e5bb9425fe881d578aeca0b2b4b3d314ec88738706f66f219c194d67179337cb"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:64c65783e96e563103d641760664125e91bd85d8e49566ee560ded4da0d3e704"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cf2430df4148b08fb4324b848672514b1385ae3807651f3567871f130a728cc3"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5397de3219a8b08ae9540c48f602996aa6b0b65d5a61683e233af8605c42b0f2"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:455705d34b4154a80ead722f4f185b04c4237e8e8e33f265cd0798d0e44825fa"}, + {file = "regex-2024.5.15-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:b2b6f1b3bb6f640c1a92be3bbfbcb18657b125b99ecf141fb3310b5282c7d4ed"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_aarch64.whl", hash = "sha256:3ad070b823ca5890cab606c940522d05d3d22395d432f4aaaf9d5b1653e47ced"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_i686.whl", hash = "sha256:5b5467acbfc153847d5adb21e21e29847bcb5870e65c94c9206d20eb4e99a384"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_ppc64le.whl", hash = "sha256:e6662686aeb633ad65be2a42b4cb00178b3fbf7b91878f9446075c404ada552f"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_s390x.whl", hash = "sha256:2b4c884767504c0e2401babe8b5b7aea9148680d2e157fa28f01529d1f7fcf67"}, + {file = "regex-2024.5.15-cp38-cp38-musllinux_1_2_x86_64.whl", hash = "sha256:3cd7874d57f13bf70078f1ff02b8b0aa48d5b9ed25fc48547516c6aba36f5741"}, + {file = "regex-2024.5.15-cp38-cp38-win32.whl", hash = "sha256:e4682f5ba31f475d58884045c1a97a860a007d44938c4c0895f41d64481edbc9"}, + {file = "regex-2024.5.15-cp38-cp38-win_amd64.whl", hash = "sha256:d99ceffa25ac45d150e30bd9ed14ec6039f2aad0ffa6bb87a5936f5782fc1569"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:13cdaf31bed30a1e1c2453ef6015aa0983e1366fad2667657dbcac7b02f67133"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:cac27dcaa821ca271855a32188aa61d12decb6fe45ffe3e722401fe61e323cd1"}, + {file = "regex-2024.5.15-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:7dbe2467273b875ea2de38ded4eba86cbcbc9a1a6d0aa11dcf7bd2e67859c435"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:64f18a9a3513a99c4bef0e3efd4c4a5b11228b48aa80743be822b71e132ae4f5"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d347a741ea871c2e278fde6c48f85136c96b8659b632fb57a7d1ce1872547600"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:1878b8301ed011704aea4c806a3cadbd76f84dece1ec09cc9e4dc934cfa5d4da"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4babf07ad476aaf7830d77000874d7611704a7fcf68c9c2ad151f5d94ae4bfc4"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:35cb514e137cb3488bce23352af3e12fb0dbedd1ee6e60da053c69fb1b29cc6c"}, + {file = "regex-2024.5.15-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_12_x86_64.manylinux2010_x86_64.whl", hash = "sha256:cdd09d47c0b2efee9378679f8510ee6955d329424c659ab3c5e3a6edea696294"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_aarch64.whl", hash = "sha256:72d7a99cd6b8f958e85fc6ca5b37c4303294954eac1376535b03c2a43eb72629"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_i686.whl", hash = "sha256:a094801d379ab20c2135529948cb84d417a2169b9bdceda2a36f5f10977ebc16"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_ppc64le.whl", hash = "sha256:c0c18345010870e58238790a6779a1219b4d97bd2e77e1140e8ee5d14df071aa"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_s390x.whl", hash = "sha256:16093f563098448ff6b1fa68170e4acbef94e6b6a4e25e10eae8598bb1694b5d"}, + {file = "regex-2024.5.15-cp39-cp39-musllinux_1_2_x86_64.whl", hash = "sha256:e38a7d4e8f633a33b4c7350fbd8bad3b70bf81439ac67ac38916c4a86b465456"}, + {file = "regex-2024.5.15-cp39-cp39-win32.whl", hash = "sha256:71a455a3c584a88f654b64feccc1e25876066c4f5ef26cd6dd711308aa538694"}, + {file = "regex-2024.5.15-cp39-cp39-win_amd64.whl", hash = "sha256:cab12877a9bdafde5500206d1020a584355a97884dfd388af3699e9137bf7388"}, + {file = "regex-2024.5.15.tar.gz", hash = "sha256:d3ee02d9e5f482cc8309134a91eeaacbdd2261ba111b0fef3748eeb4913e6a2c"}, ] [[package]] name = "requests" -version = "2.31.0" +version = "2.32.3" description = "Python HTTP for Humans." optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "requests-2.31.0-py3-none-any.whl", hash = "sha256:58cd2187c01e70e6e26505bca751777aa9f2ee0b7f4300988b709f44e013003f"}, - {file = "requests-2.31.0.tar.gz", hash = "sha256:942c5a758f98d790eaed1a29cb6eefc7ffb0d1cf7af05c3d2791656dbd6ad1e1"}, + {file = "requests-2.32.3-py3-none-any.whl", hash = "sha256:70761cfe03c773ceb22aa2f671b4757976145175cdfca038c02654d061d6dcc6"}, + {file = "requests-2.32.3.tar.gz", hash = "sha256:55365417734eb18255590a9ff9eb97e9e1da868d4ccd6402399eaf68af20a760"}, ] [package.dependencies] @@ -1346,46 +1351,31 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.3.7" +version = "0.5.0" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.macosx_11_0_arm64.macosx_10_12_universal2.whl", hash = "sha256:0e8377cccb2f07abd25e84fc5b2cbe48eeb0fea9f1719cad7caedb061d70e5ce"}, - {file = "ruff-0.3.7-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:15a4d1cc1e64e556fa0d67bfd388fed416b7f3b26d5d1c3e7d192c897e39ba4b"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d28bdf3d7dc71dd46929fafeec98ba89b7c3550c3f0978e36389b5631b793663"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:379b67d4f49774ba679593b232dcd90d9e10f04d96e3c8ce4a28037ae473f7bb"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c060aea8ad5ef21cdfbbe05475ab5104ce7827b639a78dd55383a6e9895b7c51"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:ebf8f615dde968272d70502c083ebf963b6781aacd3079081e03b32adfe4d58a"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:d48098bd8f5c38897b03604f5428901b65e3c97d40b3952e38637b5404b739a2"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:da8a4fda219bf9024692b1bc68c9cff4b80507879ada8769dc7e985755d662ea"}, - {file = "ruff-0.3.7-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6c44e0149f1d8b48c4d5c33d88c677a4aa22fd09b1683d6a7ff55b816b5d074f"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:3050ec0af72b709a62ecc2aca941b9cd479a7bf2b36cc4562f0033d688e44fa1"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:a29cc38e4c1ab00da18a3f6777f8b50099d73326981bb7d182e54a9a21bb4ff7"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_i686.whl", hash = "sha256:5b15cc59c19edca917f51b1956637db47e200b0fc5e6e1878233d3a938384b0b"}, - {file = "ruff-0.3.7-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:e491045781b1e38b72c91247cf4634f040f8d0cb3e6d3d64d38dcf43616650b4"}, - {file = "ruff-0.3.7-py3-none-win32.whl", hash = "sha256:bc931de87593d64fad3a22e201e55ad76271f1d5bfc44e1a1887edd0903c7d9f"}, - {file = "ruff-0.3.7-py3-none-win_amd64.whl", hash = "sha256:5ef0e501e1e39f35e03c2acb1d1238c595b8bb36cf7a170e7c1df1b73da00e74"}, - {file = "ruff-0.3.7-py3-none-win_arm64.whl", hash = "sha256:789e144f6dc7019d1f92a812891c645274ed08af6037d11fc65fcbc183b7d59f"}, - {file = "ruff-0.3.7.tar.gz", hash = "sha256:d5c1aebee5162c2226784800ae031f660c350e7a3402c4d1f8ea4e97e232e3ba"}, -] - -[[package]] -name = "setuptools" -version = "69.5.1" -description = "Easily download, build, install, upgrade, and uninstall Python packages" -optional = false -python-versions = ">=3.8" -files = [ - {file = "setuptools-69.5.1-py3-none-any.whl", hash = "sha256:c636ac361bc47580504644275c9ad802c50415c7522212252c033bd15f301f32"}, - {file = "setuptools-69.5.1.tar.gz", hash = "sha256:6c1fccdac05a97e598fb0ae3bbed5904ccb317337a51139dcd51453611bbb987"}, + {file = "ruff-0.5.0-py3-none-linux_armv6l.whl", hash = "sha256:ee770ea8ab38918f34e7560a597cc0a8c9a193aaa01bfbd879ef43cb06bd9c4c"}, + {file = "ruff-0.5.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:38f3b8327b3cb43474559d435f5fa65dacf723351c159ed0dc567f7ab735d1b6"}, + {file = "ruff-0.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7594f8df5404a5c5c8f64b8311169879f6cf42142da644c7e0ba3c3f14130370"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adc7012d6ec85032bc4e9065110df205752d64010bed5f958d25dbee9ce35de3"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d505fb93b0fabef974b168d9b27c3960714d2ecda24b6ffa6a87ac432905ea38"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dc5cfd3558f14513ed0d5b70ce531e28ea81a8a3b1b07f0f48421a3d9e7d80a"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:db3ca35265de239a1176d56a464b51557fce41095c37d6c406e658cf80bbb362"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1a321c4f68809fddd9b282fab6a8d8db796b270fff44722589a8b946925a2a8"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c4dfcd8d34b143916994b3876b63d53f56724c03f8c1a33a253b7b1e6bf2a7d"}, + {file = "ruff-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81e5facfc9f4a674c6a78c64d38becfbd5e4f739c31fcd9ce44c849f1fad9e4c"}, + {file = "ruff-0.5.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e589e27971c2a3efff3fadafb16e5aef7ff93250f0134ec4b52052b673cf988d"}, + {file = "ruff-0.5.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2ffbc3715a52b037bcb0f6ff524a9367f642cdc5817944f6af5479bbb2eb50e"}, + {file = "ruff-0.5.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cd096e23c6a4f9c819525a437fa0a99d1c67a1b6bb30948d46f33afbc53596cf"}, + {file = "ruff-0.5.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:46e193b36f2255729ad34a49c9a997d506e58f08555366b2108783b3064a0e1e"}, + {file = "ruff-0.5.0-py3-none-win32.whl", hash = "sha256:49141d267100f5ceff541b4e06552e98527870eafa1acc9dec9139c9ec5af64c"}, + {file = "ruff-0.5.0-py3-none-win_amd64.whl", hash = "sha256:e9118f60091047444c1b90952736ee7b1792910cab56e9b9a9ac20af94cd0440"}, + {file = "ruff-0.5.0-py3-none-win_arm64.whl", hash = "sha256:ed5c4df5c1fb4518abcb57725b576659542bdbe93366f4f329e8f398c4b71178"}, + {file = "ruff-0.5.0.tar.gz", hash = "sha256:eb641b5873492cf9bd45bc9c5ae5320648218e04386a5f0c264ad6ccce8226a1"}, ] -[package.extras] -docs = ["furo", "jaraco.packaging (>=9.3)", "jaraco.tidelift (>=1.4)", "pygments-github-lexers (==0.0.5)", "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]", "filelock (>=3.4.0)", "importlib-metadata", "ini2toml[lite] (>=0.9)", "jaraco.develop (>=7.21)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "mypy (==1.9)", "packaging (>=23.2)", "pip (>=19.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-timeout", "pytest-xdist (>=3)", "tomli", "tomli-w (>=1.0.0)", "virtualenv (>=13.0.0)", "wheel"] -testing-integration = ["build[virtualenv] (>=1.0.3)", "filelock (>=3.4.0)", "jaraco.envs (>=2.2)", "jaraco.path (>=3.2.0)", "packaging (>=23.2)", "pytest", "pytest-enabler", "pytest-xdist", "tomli", "virtualenv (>=13.0.0)", "wheel"] - [[package]] name = "six" version = "1.16.0" @@ -1431,17 +1421,18 @@ typing = ["mypy (>=1.4)"] [[package]] name = "tenacity" -version = "8.2.3" +version = "8.4.2" description = "Retry code until it succeeds" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "tenacity-8.2.3-py3-none-any.whl", hash = "sha256:ce510e327a630c9e1beaf17d42e6ffacc88185044ad85cf74c0a8887c6a0f88c"}, - {file = "tenacity-8.2.3.tar.gz", hash = "sha256:5398ef0d78e63f40007c1fb4c0bff96e1911394d2fa8d194f77619c05ff6cc8a"}, + {file = "tenacity-8.4.2-py3-none-any.whl", hash = "sha256:9e6f7cf7da729125c7437222f8a522279751cdfbe6b67bfe64f75d3a348661b2"}, + {file = "tenacity-8.4.2.tar.gz", hash = "sha256:cd80a53a79336edba8489e767f729e4f391c896956b57140b5d7511a64bbd3ef"}, ] [package.extras] -doc = ["reno", "sphinx", "tornado (>=4.5)"] +doc = ["reno", "sphinx"] +test = ["pytest", "tornado (>=4.5)", "typeguard"] [[package]] name = "tomli" @@ -1465,17 +1456,6 @@ files = [ {file = "types_boltons-23.1.0.20240331-py3-none-any.whl", hash = "sha256:58c1f57aa40b1615d48e2aca776174484f7b963ca5f3e9c6ee4743db8ede50f3"}, ] -[[package]] -name = "typing-extensions" -version = "4.11.0" -description = "Backported and Experimental Type Hints for Python 3.8+" -optional = false -python-versions = ">=3.8" -files = [ - {file = "typing_extensions-4.11.0-py3-none-any.whl", hash = "sha256:c1f94d72897edaf4ce775bb7558d5b79d8126906a14ea5ed1635921406c0387a"}, - {file = "typing_extensions-4.11.0.tar.gz", hash = "sha256:83f085bd5ca59c80295fc2a82ab5dac679cbe02b9f33f7d83af68e241bea51b0"}, -] - [[package]] name = "typing-extensions" version = "4.12.2" @@ -1489,13 +1469,13 @@ files = [ [[package]] name = "urllib3" -version = "2.2.1" +version = "2.2.2" description = "HTTP library with thread-safe connection pooling, file post, and more." optional = false python-versions = ">=3.8" files = [ - {file = "urllib3-2.2.1-py3-none-any.whl", hash = "sha256:450b20ec296a467077128bff42b73080516e71b56ff59a60a02bef2232c4fa9d"}, - {file = "urllib3-2.2.1.tar.gz", hash = "sha256:d0570876c61ab9e520d776c38acbbb5b05a776d3f9ff98a5c8fd5162a444cf19"}, + {file = "urllib3-2.2.2-py3-none-any.whl", hash = "sha256:a448b2f64d686155468037e1ace9f2d2199776e17f0a46610480d311f73e3472"}, + {file = "urllib3-2.2.2.tar.gz", hash = "sha256:dd505485549a7a552833da5e6063639d0d177c04f23bc3864e41e5dc5f612168"}, ] [package.extras] @@ -1506,13 +1486,13 @@ zstd = ["zstandard (>=0.18.0)"] [[package]] name = "virtualenv" -version = "20.26.0" +version = "20.26.3" description = "Virtual Python Environment builder" optional = false python-versions = ">=3.7" files = [ - {file = "virtualenv-20.26.0-py3-none-any.whl", hash = "sha256:0846377ea76e818daaa3e00a4365c018bc3ac9760cbb3544de542885aad61fb3"}, - {file = "virtualenv-20.26.0.tar.gz", hash = "sha256:ec25a9671a5102c8d2657f62792a27b48f016664c6873f6beed3800008577210"}, + {file = "virtualenv-20.26.3-py3-none-any.whl", hash = "sha256:8cc4a31139e796e9a7de2cd5cf2489de1217193116a8fd42328f1bd65f434589"}, + {file = "virtualenv-20.26.3.tar.gz", hash = "sha256:4c43a2a236279d9ea36a0d76f98d84bd6ca94ac4e0f4a3b9d46d05e10fea542a"}, ] [package.dependencies] @@ -1526,40 +1506,43 @@ test = ["covdefaults (>=2.3)", "coverage (>=7.2.7)", "coverage-enable-subprocess [[package]] name = "watchdog" -version = "4.0.0" +version = "4.0.1" description = "Filesystem events monitoring" optional = false python-versions = ">=3.8" files = [ - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:39cb34b1f1afbf23e9562501673e7146777efe95da24fab5707b88f7fb11649b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c522392acc5e962bcac3b22b9592493ffd06d1fc5d755954e6be9f4990de932b"}, - {file = "watchdog-4.0.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6c47bdd680009b11c9ac382163e05ca43baf4127954c5f6d0250e7d772d2b80c"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:8350d4055505412a426b6ad8c521bc7d367d1637a762c70fdd93a3a0d595990b"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c17d98799f32e3f55f181f19dd2021d762eb38fdd381b4a748b9f5a36738e935"}, - {file = "watchdog-4.0.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:4986db5e8880b0e6b7cd52ba36255d4793bf5cdc95bd6264806c233173b1ec0b"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:11e12fafb13372e18ca1bbf12d50f593e7280646687463dd47730fd4f4d5d257"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:5369136a6474678e02426bd984466343924d1df8e2fd94a9b443cb7e3aa20d19"}, - {file = "watchdog-4.0.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:76ad8484379695f3fe46228962017a7e1337e9acadafed67eb20aabb175df98b"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:45cc09cc4c3b43fb10b59ef4d07318d9a3ecdbff03abd2e36e77b6dd9f9a5c85"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:eed82cdf79cd7f0232e2fdc1ad05b06a5e102a43e331f7d041e5f0e0a34a51c4"}, - {file = "watchdog-4.0.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:ba30a896166f0fee83183cec913298151b73164160d965af2e93a20bbd2ab605"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:d18d7f18a47de6863cd480734613502904611730f8def45fc52a5d97503e5101"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:2895bf0518361a9728773083908801a376743bcc37dfa252b801af8fd281b1ca"}, - {file = "watchdog-4.0.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:87e9df830022488e235dd601478c15ad73a0389628588ba0b028cb74eb72fed8"}, - {file = "watchdog-4.0.0-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6e949a8a94186bced05b6508faa61b7adacc911115664ccb1923b9ad1f1ccf7b"}, - {file = "watchdog-4.0.0-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:6a4db54edea37d1058b08947c789a2354ee02972ed5d1e0dca9b0b820f4c7f92"}, - {file = "watchdog-4.0.0-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:d31481ccf4694a8416b681544c23bd271f5a123162ab603c7d7d2dd7dd901a07"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_aarch64.whl", hash = "sha256:8fec441f5adcf81dd240a5fe78e3d83767999771630b5ddfc5867827a34fa3d3"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_armv7l.whl", hash = "sha256:6a9c71a0b02985b4b0b6d14b875a6c86ddea2fdbebd0c9a720a806a8bbffc69f"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_i686.whl", hash = "sha256:557ba04c816d23ce98a06e70af6abaa0485f6d94994ec78a42b05d1c03dcbd50"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64.whl", hash = "sha256:d0f9bd1fd919134d459d8abf954f63886745f4660ef66480b9d753a7c9d40927"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f9b2fdca47dc855516b2d66eef3c39f2672cbf7e7a42e7e67ad2cbfcd6ba107d"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_s390x.whl", hash = "sha256:73c7a935e62033bd5e8f0da33a4dcb763da2361921a69a5a95aaf6c93aa03a87"}, - {file = "watchdog-4.0.0-py3-none-manylinux2014_x86_64.whl", hash = "sha256:6a80d5cae8c265842c7419c560b9961561556c4361b297b4c431903f8c33b269"}, - {file = "watchdog-4.0.0-py3-none-win32.whl", hash = "sha256:8f9a542c979df62098ae9c58b19e03ad3df1c9d8c6895d96c0d51da17b243b1c"}, - {file = "watchdog-4.0.0-py3-none-win_amd64.whl", hash = "sha256:f970663fa4f7e80401a7b0cbeec00fa801bf0287d93d48368fc3e6fa32716245"}, - {file = "watchdog-4.0.0-py3-none-win_ia64.whl", hash = "sha256:9a03e16e55465177d416699331b0f3564138f1807ecc5f2de9d55d8f188d08c7"}, - {file = "watchdog-4.0.0.tar.gz", hash = "sha256:e3e7065cbdabe6183ab82199d7a4f6b3ba0a438c5a512a68559846ccb76a78ec"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:da2dfdaa8006eb6a71051795856bedd97e5b03e57da96f98e375682c48850645"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:e93f451f2dfa433d97765ca2634628b789b49ba8b504fdde5837cdcf25fdb53b"}, + {file = "watchdog-4.0.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:ef0107bbb6a55f5be727cfc2ef945d5676b97bffb8425650dadbb184be9f9a2b"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:17e32f147d8bf9657e0922c0940bcde863b894cd871dbb694beb6704cfbd2fb5"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:03e70d2df2258fb6cb0e95bbdbe06c16e608af94a3ffbd2b90c3f1e83eb10767"}, + {file = "watchdog-4.0.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:123587af84260c991dc5f62a6e7ef3d1c57dfddc99faacee508c71d287248459"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:093b23e6906a8b97051191a4a0c73a77ecc958121d42346274c6af6520dec175"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:611be3904f9843f0529c35a3ff3fd617449463cb4b73b1633950b3d97fa4bfb7"}, + {file = "watchdog-4.0.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:62c613ad689ddcb11707f030e722fa929f322ef7e4f18f5335d2b73c61a85c28"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:d4925e4bf7b9bddd1c3de13c9b8a2cdb89a468f640e66fbfabaf735bd85b3e35"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cad0bbd66cd59fc474b4a4376bc5ac3fc698723510cbb64091c2a793b18654db"}, + {file = "watchdog-4.0.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:a3c2c317a8fb53e5b3d25790553796105501a235343f5d2bf23bb8649c2c8709"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:c9904904b6564d4ee8a1ed820db76185a3c96e05560c776c79a6ce5ab71888ba"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:667f3c579e813fcbad1b784db7a1aaa96524bed53437e119f6a2f5de4db04235"}, + {file = "watchdog-4.0.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:d10a681c9a1d5a77e75c48a3b8e1a9f2ae2928eda463e8d33660437705659682"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_10_9_x86_64.whl", hash = "sha256:0144c0ea9997b92615af1d94afc0c217e07ce2c14912c7b1a5731776329fcfc7"}, + {file = "watchdog-4.0.1-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:998d2be6976a0ee3a81fb8e2777900c28641fb5bfbd0c84717d89bca0addcdc5"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_10_9_x86_64.whl", hash = "sha256:e7921319fe4430b11278d924ef66d4daa469fafb1da679a2e48c935fa27af193"}, + {file = "watchdog-4.0.1-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:f0de0f284248ab40188f23380b03b59126d1479cd59940f2a34f8852db710625"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_10_9_x86_64.whl", hash = "sha256:bca36be5707e81b9e6ce3208d92d95540d4ca244c006b61511753583c81c70dd"}, + {file = "watchdog-4.0.1-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:ab998f567ebdf6b1da7dc1e5accfaa7c6992244629c0fdaef062f43249bd8dee"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_aarch64.whl", hash = "sha256:dddba7ca1c807045323b6af4ff80f5ddc4d654c8bce8317dde1bd96b128ed253"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_armv7l.whl", hash = "sha256:4513ec234c68b14d4161440e07f995f231be21a09329051e67a2118a7a612d2d"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_i686.whl", hash = "sha256:4107ac5ab936a63952dea2a46a734a23230aa2f6f9db1291bf171dac3ebd53c6"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64.whl", hash = "sha256:6e8c70d2cd745daec2a08734d9f63092b793ad97612470a0ee4cbb8f5f705c57"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_ppc64le.whl", hash = "sha256:f27279d060e2ab24c0aa98363ff906d2386aa6c4dc2f1a374655d4e02a6c5e5e"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_s390x.whl", hash = "sha256:f8affdf3c0f0466e69f5b3917cdd042f89c8c63aebdb9f7c078996f607cdb0f5"}, + {file = "watchdog-4.0.1-py3-none-manylinux2014_x86_64.whl", hash = "sha256:ac7041b385f04c047fcc2951dc001671dee1b7e0615cde772e84b01fbf68ee84"}, + {file = "watchdog-4.0.1-py3-none-win32.whl", hash = "sha256:206afc3d964f9a233e6ad34618ec60b9837d0582b500b63687e34011e15bb429"}, + {file = "watchdog-4.0.1-py3-none-win_amd64.whl", hash = "sha256:7577b3c43e5909623149f76b099ac49a1a01ca4e167d1785c76eb52fa585745a"}, + {file = "watchdog-4.0.1-py3-none-win_ia64.whl", hash = "sha256:d7b9f5f3299e8dd230880b6c55504a1f69cf1e4316275d1b215ebdd8187ec88d"}, + {file = "watchdog-4.0.1.tar.gz", hash = "sha256:eebaacf674fa25511e8867028d281e602ee6500045b57f43b08778082f7f8b44"}, ] [package.extras] @@ -1567,20 +1550,20 @@ watchmedo = ["PyYAML (>=3.10)"] [[package]] name = "zipp" -version = "3.18.1" +version = "3.19.2" description = "Backport of pathlib-compatible object wrapper for zip files" optional = false python-versions = ">=3.8" files = [ - {file = "zipp-3.18.1-py3-none-any.whl", hash = "sha256:206f5a15f2af3dbaee80769fb7dc6f249695e940acca08dfb2a4769fe61e538b"}, - {file = "zipp-3.18.1.tar.gz", hash = "sha256:2884ed22e7d8961de1c9a05142eb69a247f120291bc0206a00a7642f09b5b715"}, + {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", "more-itertools", "pytest (>=6)", "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)"] [metadata] lock-version = "2.0" python-versions = ">=3.9" -content-hash = "ea0748c83bcfb50bb02f0e5394a95f80d7730f8e7f622989675246ae5448d32f" +content-hash = "8171a64e602e81c7a7380f3175f6745129c2ed2464acdb49c5a9d784836839f5" diff --git a/pyproject.toml b/pyproject.toml index c06b63f..f76b01a 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -22,30 +22,30 @@ classifiers = [ [tool.poetry.dependencies] python = ">=3.9" -pydantic = "^2.8.0" -typing-extensions =">=4.11.0" -pydantic-extra-types =">=2.7.0" -pycountry = ">=23.12.11" +pydantic = ">=2.8.2" +typing-extensions =">=4.12.2" +pydantic-extra-types =">=2.9.0" +pycountry = ">=24.6.1" httpx = ">=0.27.0" boltons = ">=24.0.0" stamina = ">=24.2.0" -nh3 = "^0.2.17" -html2text = "^2024.2.26" -importlib-metadata = { version = ">=7.1.0", python = "<3.10" } +nh3 = ">=0.2.17" +html2text = ">=2024.2.26" +importlib-metadata = { version = ">=8.0.0", python = "<3.10" } eval-type-backport = { version = ">=0.2.0", python = "<3.10" } backports-strenum = {version = ">=1.3.1", python = "<3.11"} [tool.poetry.group.dev.dependencies] -ruff = "^0.3.5" -mypy = "^1.9.0" +ruff = "^0.5.0" +mypy = "^1.10.1" types-boltons = "^23.1.0.20240331" -pytest = "^8.1.1" +pytest = "^8.2.2" pytest-asyncio = "^0.23.5.post1" -pre-commit = "^3.7.0" -coverage = "^7.5.0" +pre-commit = "^3.7.1" +coverage = "^7.5.4" [tool.poetry.group.docs.dependencies] -mkdocs-material = "^9.5.18" +mkdocs-material = "^9.5.28" mkdocstrings = {extras = ["python"], version = "^0.24.0"} mkdocs-autorefs = "^1.0.1" @@ -59,6 +59,7 @@ fixable = ["ALL"] [tool.mypy] strict = true pretty = true +exclude = "/tests/" [tool.pytest.ini_options] asyncio_mode = "auto" diff --git a/src/pyanilist/_clients/_sync.py b/src/pyanilist/_clients/_sync.py index 05adeee..bfcf918 100644 --- a/src/pyanilist/_clients/_sync.py +++ b/src/pyanilist/_clients/_sync.py @@ -18,9 +18,7 @@ class AniList: @validate_call - def __init__( - self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: Any - ) -> None: + def __init__(self, api_url: str = "https://graphql.anilist.co", retries: PositiveInt = 5, **kwargs: Any) -> None: """ AniList API client. @@ -69,7 +67,7 @@ def _post_request(self, **kwargs: Any) -> Response: with attempt: with Client(**self.kwargs) as client: response = client.post(self.api_url, json=payload).raise_for_status() - + return response @validate_call diff --git a/src/pyanilist/_compat.py b/src/pyanilist/_compat.py index 6365446..ba07533 100644 --- a/src/pyanilist/_compat.py +++ b/src/pyanilist/_compat.py @@ -1,4 +1,5 @@ """Compatibility module to for older python versions""" + from __future__ import annotations import sys diff --git a/src/pyanilist/_models.py b/src/pyanilist/_models.py index 94a0d84..1cf86e6 100644 --- a/src/pyanilist/_models.py +++ b/src/pyanilist/_models.py @@ -82,7 +82,7 @@ def iso_format(self) -> str: else: return "" - + def as_int(self) -> FuzzyDateInt: """ Return an 8 digit long date integer (YYYYMMDD). diff --git a/src/pyanilist/_parser.py b/src/pyanilist/_parser.py index aa1133f..75eb38b 100644 --- a/src/pyanilist/_parser.py +++ b/src/pyanilist/_parser.py @@ -4,9 +4,10 @@ from ._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter -if TYPE_CHECKING: # pragma: no cover +if TYPE_CHECKING: # pragma: no cover from httpx import Response + def process_description(dictionary: dict[str, Any]) -> dict[str, Any]: """ Anilist's description field takes a parameter `asHtml: boolean`, effectively @@ -60,6 +61,7 @@ def process_description(dictionary: dict[str, Any]) -> dict[str, Any]: text=text_description, ) + def post_process_response(response: Response) -> dict[str, Any]: """ Post-processes the response from AniList API. @@ -122,4 +124,4 @@ def post_process_response(response: Response) -> dict[str, Any]: # self explanatory, details on why # are in the function docstring - return remove_null_fields(dictionary) \ No newline at end of file + return remove_null_fields(dictionary) diff --git a/src/pyanilist/_utils.py b/src/pyanilist/_utils.py index d717332..6f209d1 100644 --- a/src/pyanilist/_utils.py +++ b/src/pyanilist/_utils.py @@ -101,6 +101,7 @@ def remove_null_fields(dictionary: dict[str, Any]) -> dict[str, Any]: """ return remap(dictionary, lambda path, key, value: value not in [None, {}, []]) # type: ignore + def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: """ Anilist doesn't stick to a single casing. @@ -179,11 +180,11 @@ def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: } query_vars = {} - + for key, value in vars.items(): if value is not None: if isinstance(value, Iterable) and not isinstance(value, str): value = set(value) query_vars[casing[key]] = value - return query_vars \ No newline at end of file + return query_vars diff --git a/src/pyanilist/_version.py b/src/pyanilist/_version.py index 2fefceb..d0d415e 100644 --- a/src/pyanilist/_version.py +++ b/src/pyanilist/_version.py @@ -10,6 +10,7 @@ class Version(NamedTuple): minor: int micro: int + def _get_version() -> str: """ Get the version of pyanilist diff --git a/tests/test_anilist.py b/tests/test_anilist.py index b50a969..42f4461 100644 --- a/tests/test_anilist.py +++ b/tests/test_anilist.py @@ -117,7 +117,7 @@ def test_anilist_with_constraints() -> None: ("Katsuyuki Kodera", "Storyboard (eps 5, 9, 13)"), ("Kenji Nagasaki", "Storyboard (OP, ED, eps 1, 2)"), ] - assert media.site_url.__str__() =="https://anilist.co/anime/21459" + assert media.site_url.__str__() == "https://anilist.co/anime/21459" def test_anilist_id() -> None: diff --git a/tests/test_models.py b/tests/test_models.py index d8f95ac..914e26b 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -10,4 +10,4 @@ def test_fuzzy_date() -> None: assert FuzzyDate(year=2023, month=1).as_int() == 20230100 assert FuzzyDate(year=2023).as_int() == 20230000 - assert FuzzyDate().iso_format() == "" \ No newline at end of file + assert FuzzyDate().iso_format() == "" diff --git a/tests/test_utils.py b/tests/test_utils.py index 4ed48d5..a38ae85 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,5 +1,12 @@ -from pyanilist._utils import flatten, markdown_formatter, remove_null_fields, sanitize_description, text_formatter, query_variables_constructor from pyanilist import MediaSource +from pyanilist._utils import ( + flatten, + markdown_formatter, + query_variables_constructor, + remove_null_fields, + sanitize_description, + text_formatter, +) from .mock_descriptions import BloomIntoYouAnthologyDescriptions @@ -123,4 +130,4 @@ def test_query_variables_constructor() -> None: "search": "Attack on Titan", "id_not_in": {1, 2, 3, 4, 5}, "source_in": {MediaSource.ANIME, MediaSource.MANGA}, - } \ No newline at end of file + } From e8bf608f21b47a92bdc9799e8bae4f7a9e9146e7 Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Fri, 5 Jul 2024 10:39:49 +0530 Subject: [PATCH 4/6] fix: workaround pydantic bug --- src/pyanilist/__init__.py | 7 ++- src/pyanilist/_clients/_async.py | 7 ++- src/pyanilist/_clients/_sync.py | 10 ++-- src/pyanilist/_types.py | 20 +++----- src/pyanilist/_utils.py | 25 ++++----- tests/test_models.py | 4 +- tests/test_utils.py | 88 ++++++++++++++++++++++++++------ 7 files changed, 107 insertions(+), 54 deletions(-) diff --git a/src/pyanilist/__init__.py b/src/pyanilist/__init__.py index 1f39b2c..0d8e12f 100644 --- a/src/pyanilist/__init__.py +++ b/src/pyanilist/__init__.py @@ -11,6 +11,7 @@ MediaRankType, MediaRelation, MediaSeason, + MediaSort, MediaSource, MediaStatus, MediaType, @@ -36,10 +37,10 @@ StaffName, Studio, ) -from ._types import YearsActive +from ._types import FuzzyDateInt, YearsActive from ._version import Version, _get_version -__version__ = _get_version() +__version__ = _get_version() __version_tuple__ = Version(*map(int, __version__.split("."))) __all__ = [ @@ -53,11 +54,13 @@ "MediaRankType", "MediaRelation", "MediaSeason", + "MediaSort", "MediaSource", "MediaStatus", "MediaType", # Types "YearsActive", + "FuzzyDateInt", # Models "AiringSchedule", "Character", diff --git a/src/pyanilist/_clients/_async.py b/src/pyanilist/_clients/_async.py index bc8b6df..daf9821 100644 --- a/src/pyanilist/_clients/_async.py +++ b/src/pyanilist/_clients/_async.py @@ -5,7 +5,6 @@ from httpx import AsyncClient, HTTPError, Response from pydantic import PositiveInt, validate_call -from pydantic_extra_types.country import CountryAlpha2 as CountryCode from stamina import retry_context from .._enums import MediaFormat, MediaSeason, MediaSort, MediaSource, MediaStatus, MediaType @@ -13,7 +12,7 @@ from .._parser import post_process_response from .._query import query_string from .._types import FuzzyDateInt -from .._utils import query_variables_constructor +from .._utils import to_anilist_case class AsyncAniList: @@ -60,7 +59,7 @@ async def _post_request(self, **kwargs: Any) -> Response: payload = { "query": query_string, - "variables": query_variables_constructor(kwargs), + "variables": {to_anilist_case(key): value for key, value in kwargs.items() if value is not None}, } async for attempt in retry_context(on=HTTPError, attempts=self.retries): @@ -99,7 +98,7 @@ async def get( average_score: int | None = None, popularity: int | None = None, source: MediaSource | None = None, - country_of_origin: CountryCode | str | None = None, + country_of_origin: str | None = None, is_licensed: bool | None = None, id_not: int | None = None, id_in: Iterable[int] | None = None, diff --git a/src/pyanilist/_clients/_sync.py b/src/pyanilist/_clients/_sync.py index bfcf918..0427e39 100644 --- a/src/pyanilist/_clients/_sync.py +++ b/src/pyanilist/_clients/_sync.py @@ -1,19 +1,17 @@ from __future__ import annotations -from collections.abc import Iterable from typing import Any from httpx import Client, HTTPError, Response from pydantic import PositiveInt, validate_call -from pydantic_extra_types.country import CountryAlpha2 as CountryCode from stamina import retry_context from .._enums import MediaFormat, MediaSeason, MediaSort, MediaSource, MediaStatus, MediaType from .._models import Media from .._parser import post_process_response from .._query import query_string -from .._types import FuzzyDateInt -from .._utils import query_variables_constructor +from .._types import FuzzyDateInt, Iterable +from .._utils import to_anilist_case class AniList: @@ -60,7 +58,7 @@ def _post_request(self, **kwargs: Any) -> Response: payload = { "query": query_string, - "variables": query_variables_constructor(kwargs), + "variables": {to_anilist_case(key): value for key, value in kwargs.items() if value is not None}, } for attempt in retry_context(on=HTTPError, attempts=self.retries): @@ -98,7 +96,7 @@ def get( average_score: int | None = None, popularity: int | None = None, source: MediaSource | None = None, - country_of_origin: CountryCode | str | None = None, + country_of_origin: str | None = None, is_licensed: bool | None = None, id_not: int | None = None, id_in: Iterable[int] | None = None, diff --git a/src/pyanilist/_types.py b/src/pyanilist/_types.py index e627b28..f4602d5 100644 --- a/src/pyanilist/_types.py +++ b/src/pyanilist/_types.py @@ -1,16 +1,15 @@ -""" -Aside from providing it's own types, this module also re-exports the following from pydantic for convenience: -- [HttpUrl](https://docs.pydantic.dev/latest/api/networks/#pydantic.networks.HttpUrl) -- [Color](https://docs.pydantic.dev/latest/api/pydantic_extra_types_color/#pydantic_extra_types.color.Color) -- [CountryAlpha2 as CountryCoude](https://docs.pydantic.dev/latest/api/pydantic_extra_types_country/#pydantic_extra_types.country.CountryAlpha2) -""" - from __future__ import annotations from typing import Annotated from pydantic import Field -from typing_extensions import NamedTuple +from typing_extensions import NamedTuple, TypeAlias, TypeVar, Union + +# A simpler Iterable type instead of collections.abc.Iterable +# to stop pydantic from converting them to ValidatorIterator +# https://github.com/pydantic/pydantic/issues/9541 +T = TypeVar("T") +Iterable: TypeAlias = Union[set[T], tuple[T, ...], list[T]] class YearsActive(NamedTuple): @@ -31,8 +30,3 @@ class YearsActive(NamedTuple): description="8 digit long date integer (YYYYMMDD). Unknown dates represented by 0. E.g. 2016: 20160000, May 1976: 19760500", ), ] - - -__all__ = [ - "YearsActive", -] diff --git a/src/pyanilist/_utils.py b/src/pyanilist/_utils.py index 6f209d1..94f9d6d 100644 --- a/src/pyanilist/_utils.py +++ b/src/pyanilist/_utils.py @@ -1,7 +1,6 @@ from __future__ import annotations import re -from collections.abc import Iterable from typing import Any import nh3 @@ -102,13 +101,23 @@ def remove_null_fields(dictionary: dict[str, Any]) -> dict[str, Any]: return remap(dictionary, lambda path, key, value: value not in [None, {}, []]) # type: ignore -def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: +def to_anilist_case(var: str) -> str: """ Anilist doesn't stick to a single casing. Most of it is camelCase but then there's some made up stuff in there too. So can do nothing but create a mapping from snake_case to anilistCase + + Parameters + ---------- + var : str + A snake_case variable. + + Returns + ------- + str + Same thing but in anilist's case. """ - casing = { + casemap = { "id": "id", "id_mal": "idMal", "start_date": "startDate", @@ -179,12 +188,4 @@ def query_variables_constructor(vars: dict[str, Any]) -> dict[str, Any]: "sort": "sort", } - query_vars = {} - - for key, value in vars.items(): - if value is not None: - if isinstance(value, Iterable) and not isinstance(value, str): - value = set(value) - query_vars[casing[key]] = value - - return query_vars + return casemap[var] \ No newline at end of file diff --git a/tests/test_models.py b/tests/test_models.py index 914e26b..1e3332a 100644 --- a/tests/test_models.py +++ b/tests/test_models.py @@ -5,9 +5,9 @@ def test_fuzzy_date() -> None: assert FuzzyDate(year=2023, month=1, day=4).iso_format() == "2023-01-04" assert FuzzyDate(year=2023, month=1).iso_format() == "2023-01" assert FuzzyDate(year=2023).iso_format() == "2023" + assert FuzzyDate().iso_format() == "" assert FuzzyDate(year=2023, month=1, day=4).as_int() == 20230104 assert FuzzyDate(year=2023, month=1).as_int() == 20230100 assert FuzzyDate(year=2023).as_int() == 20230000 - - assert FuzzyDate().iso_format() == "" + assert FuzzyDate().as_int() == 10000000 diff --git a/tests/test_utils.py b/tests/test_utils.py index a38ae85..13c2f24 100644 --- a/tests/test_utils.py +++ b/tests/test_utils.py @@ -1,11 +1,10 @@ -from pyanilist import MediaSource from pyanilist._utils import ( flatten, markdown_formatter, - query_variables_constructor, remove_null_fields, sanitize_description, text_formatter, + to_anilist_case, ) from .mock_descriptions import BloomIntoYouAnthologyDescriptions @@ -116,18 +115,77 @@ def test_formatters() -> None: def test_query_variables_constructor() -> None: - kwargs = { - "id": 123456, - "is_licensed": True, - "search": "Attack on Titan", - "id_not_in": [1, 2, 3, 4, 5, 5, 5], - "source_in": [MediaSource.ANIME, MediaSource.ANIME, MediaSource.MANGA], - } - assert query_variables_constructor(kwargs) == { - "id": 123456, - "isLicensed": True, - "search": "Attack on Titan", - "id_not_in": {1, 2, 3, 4, 5}, - "source_in": {MediaSource.ANIME, MediaSource.MANGA}, + casemap = { + "id": "id", + "id_mal": "idMal", + "start_date": "startDate", + "end_date": "endDate", + "season": "season", + "season_year": "seasonYear", + "type": "type", + "format": "format", + "status": "status", + "episodes": "episodes", + "chapters": "chapters", + "duration": "duration", + "volumes": "volumes", + "is_adult": "isAdult", + "genre": "genre", + "tag": "tag", + "minimum_tag_rank": "minimumTagRank", + "tag_category": "tagCategory", + "licensed_by": "licensedBy", + "licensed_by_id": "licensedById", + "average_score": "averageScore", + "popularity": "popularity", + "source": "source", + "country_of_origin": "countryOfOrigin", + "is_licensed": "isLicensed", + "search": "search", + "id_not": "id_not", + "id_in": "id_in", + "id_not_in": "id_not_in", + "id_mal_not": "idMal_not", + "id_mal_in": "idMal_in", + "id_mal_not_in": "idMal_not_in", + "start_date_greater": "startDate_greater", + "start_date_lesser": "startDate_lesser", + "start_date_like": "startDate_like", + "end_date_greater": "endDate_greater", + "end_date_lesser": "endDate_lesser", + "end_date_like": "endDate_like", + "format_in": "format_in", + "format_not": "format_not", + "format_not_in": "format_not_in", + "status_in": "status_in", + "status_not": "status_not", + "status_not_in": "status_not_in", + "episodes_greater": "episodes_greater", + "episodes_lesser": "episodes_lesser", + "duration_greater": "duration_greater", + "duration_lesser": "duration_lesser", + "chapters_greater": "chapters_greater", + "chapters_lesser": "chapters_lesser", + "volumes_greater": "volumes_greater", + "volumes_lesser": "volumes_lesser", + "genre_in": "genre_in", + "genre_not_in": "genre_not_in", + "tag_in": "tag_in", + "tag_not_in": "tag_not_in", + "tag_category_in": "tagCategory_in", + "tag_category_not_in": "tagCategory_not_in", + "licensed_by_in": "licensedBy_in", + "licensed_by_id_in": "licensedById_in", + "average_score_not": "averageScore_not", + "average_score_greater": "averageScore_greater", + "average_score_lesser": "averageScore_lesser", + "popularity_not": "popularity_not", + "popularity_greater": "popularity_greater", + "popularity_lesser": "popularity_lesser", + "source_in": "source_in", + "sort": "sort", } + + for key, value in casemap.items(): + assert to_anilist_case(key) == value From b257bb2a9a3c052c26fe35ff85d240081ba4eb97 Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:37:18 +0530 Subject: [PATCH 5/6] docs: update --- README.md | 100 +++++----------------------------- docs/api-reference/clients.md | 12 ---- docs/api-reference/enums.md | 22 +++++++- docs/api-reference/types.md | 3 + docs/examples.md | 78 +++++++++----------------- docs/index.md | 98 ++++----------------------------- poetry.lock | 70 ++++++++++++------------ pyproject.toml | 4 +- src/pyanilist/_types.py | 3 +- 9 files changed, 113 insertions(+), 277 deletions(-) diff --git a/README.md b/README.md index 8f8a8cf..e53b809 100644 --- a/README.md +++ b/README.md @@ -32,8 +32,7 @@ ## About - Supports both sync and async. -- Provides easy access to almost every field present in AniList's `Media` type. -- Only supports querying the `Media` type +- Only supports querying the `Media` type. ## Installation @@ -45,91 +44,18 @@ pip install pyanilist ## Usage -1. `AniList()` - Synchronous class - - `search()` - Search a media - - ```py - from pyanilist import AniList, MediaType - - media = AniList().search("Attack on Titan", type=MediaType.ANIME) - - print(media.title.romaji) - """ - Shingeki no Kyojin - """ - print(media.site_url) - """ - https://anilist.co/anime/16498 - """ - print(media.episodes) - """ - 25 - """ - ``` - - `get()` - Get a media by it's AniList ID - - ```py - from pyanilist import AniList - - media = AniList().get(21459) - - print(media.title.english) - """ - My Hero Academia - """ - print(media.site_url) - """ - https://anilist.co/anime/21459 - """ - print(media.episodes) - """ - 13 - """ - ``` - -2. `AsyncAniList()` - Asynchronous class - - `search()` - Search a media - - ```py - import asyncio - from pyanilist import AsyncAniList, MediaType - - media = asyncio.run(AsyncAniList().search("Attack on Titan", type=MediaType.ANIME)) - - print(media.title.romaji) - """ - Shingeki no Kyojin - """ - print(media.site_url) - """ - https://anilist.co/anime/16498 - """ - print(media.episodes) - """ - 25 - """ - ``` - - `get()` - Get a media by it's AniList ID - - ```py - import asyncio - from pyanilist import AsyncAniList - - media = asyncio.run(AsyncAniList().get(21459)) - - print(media.title.english) - """ - My Hero Academia - """ - print(media.site_url) - """ - https://anilist.co/anime/21459 - """ - print(media.episodes) - """ - 13 - """ - ``` +```py +from pyanilist import AniList + +media = AniList().get("My Hero Academia") + +print(media.title.romaji) +#> Boku no Hero Academia +print(media.site_url) +#> https://anilist.co/anime/21459 +print(media.episodes) +#> 13 +``` ## Docs diff --git a/docs/api-reference/clients.md b/docs/api-reference/clients.md index 06f94a4..ceb60e5 100644 --- a/docs/api-reference/clients.md +++ b/docs/api-reference/clients.md @@ -1,14 +1,2 @@ ::: pyanilist.AniList - options: - members: - - __init__ - - search - - get - - ::: pyanilist.AsyncAniList - options: - members: - - __init__ - - search - - get \ No newline at end of file diff --git a/docs/api-reference/enums.md b/docs/api-reference/enums.md index 26fda4b..3c43a48 100644 --- a/docs/api-reference/enums.md +++ b/docs/api-reference/enums.md @@ -1,11 +1,31 @@ ::: pyanilist._enums.BaseStrEnum ::: pyanilist._enums.CharacterRole + options: + members: true ::: pyanilist._enums.ExternalLinkType + options: + members: true ::: pyanilist._enums.MediaFormat + options: + members: true ::: pyanilist._enums.MediaRankType + options: + members: true ::: pyanilist._enums.MediaRelation + options: + members: true ::: pyanilist._enums.MediaSeason + options: + members: true ::: pyanilist._enums.MediaSort + options: + members: true ::: pyanilist._enums.MediaSource + options: + members: true ::: pyanilist._enums.MediaStatus -::: pyanilist._enums.MediaType \ No newline at end of file + options: + members: true +::: pyanilist._enums.MediaType + options: + members: true diff --git a/docs/api-reference/types.md b/docs/api-reference/types.md index d5a1a49..1db306c 100644 --- a/docs/api-reference/types.md +++ b/docs/api-reference/types.md @@ -1,2 +1,5 @@ ::: pyanilist._types.YearsActive + options: + members: true ::: pyanilist._types.FuzzyDateInt +::: pyanilist._types.Iterable diff --git a/docs/examples.md b/docs/examples.md index c49b73a..3157fdc 100644 --- a/docs/examples.md +++ b/docs/examples.md @@ -1,19 +1,17 @@ # Examples !!! note - These examples use `pyanilist.AniList` but you can do the same thing with `pyanilist.AsyncAniList` since they share the same methods + These examples use [`pyanilist.AniList`][pyanilist.AniList] but you can do the same thing with [`pyanilist.AsyncAniList`][pyanilist.AsyncAniList] since they share the same methods ## AniList ID ```py from pyanilist import AniList -media = AniList().get(16498) +media = AniList().get(id=16498) print(media.title.english) -""" -Attack on Titan -""" +#> Attack on Titan ``` ## Search @@ -21,27 +19,21 @@ Attack on Titan ```py from pyanilist import AniList -media = AniList().search("Attack on titan") +media = AniList().get("Attack on titan") print(media.format) -""" -TV -""" +#> TV print(media.title.romaji) -""" -Shingeki no Kyojin -""" +#> Shingeki no Kyojin print(media.episodes) -""" -25 -""" +#> 25 ``` ## Search with constraints ```py from pyanilist import AniList, MediaSeason, MediaType, MediaStatus, MediaFormat -media = AniList().search( +media = AniList().get( "My Hero Academia", season=MediaSeason.SPRING, season_year=2016, @@ -51,17 +43,11 @@ media = AniList().search( ) print(media.title.romaji) -""" -Boku no Hero Academia -""" +#> Boku no Hero Academia print(media.start_date.iso_format()) -""" -2016-04-03 -""" +#> 2016-04-03 print(media.site_url) -""" -https://anilist.co/anime/21459 -""" +#> https://anilist.co/anime/21459 ``` ## Related media @@ -69,21 +55,17 @@ https://anilist.co/anime/21459 ```py from pyanilist import AniList -media = AniList().search("violet evergarden") +media = AniList().get("violet evergarden") print(media.format) -""" -TV -""" +#> TV for relation in media.relations: print(f"{relation.title.romaji} ({relation.format}) - {relation.site_url}") -""" -Violet Evergarden: Kitto "Ai" wo Shiru Hi ga Kuru no Darou (OVA) - https://anilist.co/anime/101432 -Violet Evergarden (NOVEL) - https://anilist.co/manga/97298 -Violet Evergarden Gaiden: Eien to Jidou Shuki Ningyou (MOVIE) - https://anilist.co/anime/109190 -Violet Evergarden CM (ONA) - https://anilist.co/anime/154164 -""" + #> Violet Evergarden: Kitto "Ai" wo Shiru Hi ga Kuru no Darou (OVA) - https://anilist.co/anime/101432 + #> Violet Evergarden (NOVEL) - https://anilist.co/manga/97298 + #> Violet Evergarden Gaiden: Eien to Jidou Shuki Ningyou (MOVIE) - https://anilist.co/anime/109190 + #> Violet Evergarden CM (ONA) - https://anilist.co/anime/154164 ``` ## Characters @@ -91,7 +73,7 @@ Violet Evergarden CM (ONA) - https://anilist.co/anime/154164 ```py from pyanilist import AniList, CharacterRole -media = AniList().get(20954) +media = AniList().get(id=20954) all_characters = [character.name.full for character in media.characters] @@ -99,19 +81,15 @@ all_characters = [character.name.full for character in media.characters] main_characters = [character.name.full for character in media.characters if character.role is CharacterRole.MAIN] print(all_characters) -""" -['Shouya Ishida', 'Shouko Nishimiya', 'Yuzuru Nishimiya', 'Naoka Ueno', 'Miyako Ishida', 'Maria Ishida', 'Miki Kawai', 'Satoshi Mashiba', 'Tomohiro Nagatsuka', 'Yaeko Nishimiya', 'Ito Nishimiya', 'Miyoko Sahara', 'Kazuki Shimada', 'Takeuchi', 'Pedro', 'Keisuke Hirose', 'Ishida no Ane', 'Kita'] -""" +#> ['Shouya Ishida', 'Shouko Nishimiya', 'Yuzuru Nishimiya', 'Naoka Ueno', 'Miyako Ishida', 'Maria Ishida', 'Miki Kawai', 'Satoshi Mashiba', 'Tomohiro Nagatsuka', 'Yaeko Nishimiya', 'Ito Nishimiya', 'Miyoko Sahara', 'Kazuki Shimada', 'Takeuchi', 'Pedro', 'Keisuke Hirose', 'Ishida no Ane', 'Kita'] print(main_characters) -""" -['Shouya Ishida', 'Shouko Nishimiya'] -""" +#> ['Shouya Ishida', 'Shouko Nishimiya'] ``` ## Retries -AniList API is flaky, sometimes it might return an error for a perfectly valid request. `pyanilist` handles this by simply retrying failed requests a specified number of times (default is 5) before raising an error. Every subsequent retry also adds an additional one-second delay between requests. +AniList API is flaky, sometimes it might return an error for a perfectly valid request. `pyanilist` handles this by simply retrying failed requests a specified number of times (default is 5) before raising an error. Every subsequent retry also adds an additional delay between requests. ```py from pyanilist import AniList @@ -119,17 +97,15 @@ from pyanilist import AniList # Configure the number of retries. Setting it to 1 disables retrying. anilist = AniList(retries=1) -media = anilist.search("violet evergarden") +media = anilist.get("violet evergarden") print(f"{media.title.english} - {media.site_url}") -""" -Violet Evergarden - https://anilist.co/anime/21827 -""" +#> Violet Evergarden - https://anilist.co/anime/21827 ``` ## Client -`pyanilist` gives you direct access to the internal [`httpx.Client()`](https://www.python-httpx.org/api/#client) used to send the POST request. +`pyanilist` lets you pass keyword arguments to the internal [`httpx.Client`](https://www.python-httpx.org/api/#client) used to send the POST request. ```py from pyanilist import AniList @@ -139,10 +115,8 @@ headers = {'user-agent': 'my-app/0.0.1'} # You can pass any httpx.Client() keyword argument to AniList() anilist = AniList(headers=headers) -media = anilist.get(105333) +media = anilist.get(id=105333) print(media.title.english) -""" -Dr. STONE -""" +#> Dr. STONE ``` diff --git a/docs/index.md b/docs/index.md index 61aabe3..0f65f75 100644 --- a/docs/index.md +++ b/docs/index.md @@ -28,8 +28,7 @@ ## About - Supports both sync and async. -- Provides easy access to almost every field present in AniList's `Media` type. -- Only supports querying the `Media` type +- Only supports querying the `Media` type. ## Installation @@ -41,93 +40,18 @@ pip install pyanilist ## Usage -PyAniList offers two main classes: +```py +from pyanilist import AniList -1. `AniList()` - Synchronous class - - `search()` - Search a media +media = AniList().get("My Hero Academia") - ```py - from pyanilist import AniList, MediaType - - media = AniList().search("Attack on Titan", type=MediaType.ANIME) - - print(media.title.romaji) - """ - Shingeki no Kyojin - """ - print(media.site_url) - """ - https://anilist.co/anime/16498 - """ - print(media.episodes) - """ - 25 - """ - ``` - - `get()` - Get a media by it's AniList ID - - ```py - from pyanilist import AniList - - media = AniList().get(21459) - - print(media.title.english) - """ - My Hero Academia - """ - print(media.site_url) - """ - https://anilist.co/anime/21459 - """ - print(media.episodes) - """ - 13 - """ - ``` - -2. `AsyncAniList()` - Asynchronous class - - `search()` - Search a media - - ```py - import asyncio - from pyanilist import AsyncAniList, MediaType - - media = asyncio.run(AsyncAniList().search("Attack on Titan", type=MediaType.ANIME)) - - print(media.title.romaji) - """ - Shingeki no Kyojin - """ - print(media.site_url) - """ - https://anilist.co/anime/16498 - """ - print(media.episodes) - """ - 25 - """ - ``` - - `get()` - Get a media by it's AniList ID - - ```py - import asyncio - from pyanilist import AsyncAniList - - media = asyncio.run(AsyncAniList().get(21459)) - - print(media.title.english) - """ - My Hero Academia - """ - print(media.site_url) - """ - https://anilist.co/anime/21459 - """ - print(media.episodes) - """ - 13 - """ - ``` +print(media.title.romaji) +#> Boku no Hero Academia +print(media.site_url) +#> https://anilist.co/anime/21459 +print(media.episodes) +#> 13 +``` ## License diff --git a/poetry.lock b/poetry.lock index 98e908a..bae9903 100644 --- a/poetry.lock +++ b/poetry.lock @@ -1,4 +1,4 @@ -# This file is automatically @generated by Poetry 1.8.2 and should not be changed by hand. +# This file is automatically @generated by Poetry 1.8.3 and should not be changed by hand. [[package]] name = "annotated-types" @@ -707,13 +707,13 @@ files = [ [[package]] name = "mkdocstrings" -version = "0.24.3" +version = "0.25.1" description = "Automatic documentation from sources, for MkDocs." optional = false python-versions = ">=3.8" files = [ - {file = "mkdocstrings-0.24.3-py3-none-any.whl", hash = "sha256:5c9cf2a32958cd161d5428699b79c8b0988856b0d4a8c5baf8395fc1bf4087c3"}, - {file = "mkdocstrings-0.24.3.tar.gz", hash = "sha256:f327b234eb8d2551a306735436e157d0a22d45f79963c60a8b585d5f7a94c1d2"}, + {file = "mkdocstrings-0.25.1-py3-none-any.whl", hash = "sha256:da01fcc2670ad61888e8fe5b60afe9fee5781017d67431996832d63e887c2e51"}, + {file = "mkdocstrings-0.25.1.tar.gz", hash = "sha256:c3a2515f31577f311a9ee58d089e4c51fc6046dbd9e9b4c3de4c3194667fe9bf"}, ] [package.dependencies] @@ -736,18 +736,18 @@ python-legacy = ["mkdocstrings-python-legacy (>=0.2.1)"] [[package]] name = "mkdocstrings-python" -version = "1.10.0" +version = "1.10.5" description = "A Python handler for mkdocstrings." optional = false python-versions = ">=3.8" files = [ - {file = "mkdocstrings_python-1.10.0-py3-none-any.whl", hash = "sha256:ba833fbd9d178a4b9d5cb2553a4df06e51dc1f51e41559a4d2398c16a6f69ecc"}, - {file = "mkdocstrings_python-1.10.0.tar.gz", hash = "sha256:71678fac657d4d2bb301eed4e4d2d91499c095fd1f8a90fa76422a87a5693828"}, + {file = "mkdocstrings_python-1.10.5-py3-none-any.whl", hash = "sha256:92e3c588ef1b41151f55281d075de7558dd8092e422cb07a65b18ee2b0863ebb"}, + {file = "mkdocstrings_python-1.10.5.tar.gz", hash = "sha256:acdc2a98cd9d46c7ece508193a16ca03ccabcb67520352b7449f84b57c162bdf"}, ] [package.dependencies] -griffe = ">=0.44" -mkdocstrings = ">=0.24.2" +griffe = ">=0.47" +mkdocstrings = ">=0.25" [[package]] name = "mypy" @@ -1351,29 +1351,29 @@ use-chardet-on-py3 = ["chardet (>=3.0.2,<6)"] [[package]] name = "ruff" -version = "0.5.0" +version = "0.5.1" description = "An extremely fast Python linter and code formatter, written in Rust." optional = false python-versions = ">=3.7" files = [ - {file = "ruff-0.5.0-py3-none-linux_armv6l.whl", hash = "sha256:ee770ea8ab38918f34e7560a597cc0a8c9a193aaa01bfbd879ef43cb06bd9c4c"}, - {file = "ruff-0.5.0-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:38f3b8327b3cb43474559d435f5fa65dacf723351c159ed0dc567f7ab735d1b6"}, - {file = "ruff-0.5.0-py3-none-macosx_11_0_arm64.whl", hash = "sha256:7594f8df5404a5c5c8f64b8311169879f6cf42142da644c7e0ba3c3f14130370"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:adc7012d6ec85032bc4e9065110df205752d64010bed5f958d25dbee9ce35de3"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d505fb93b0fabef974b168d9b27c3960714d2ecda24b6ffa6a87ac432905ea38"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:9dc5cfd3558f14513ed0d5b70ce531e28ea81a8a3b1b07f0f48421a3d9e7d80a"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:db3ca35265de239a1176d56a464b51557fce41095c37d6c406e658cf80bbb362"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b1a321c4f68809fddd9b282fab6a8d8db796b270fff44722589a8b946925a2a8"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:2c4dfcd8d34b143916994b3876b63d53f56724c03f8c1a33a253b7b1e6bf2a7d"}, - {file = "ruff-0.5.0-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81e5facfc9f4a674c6a78c64d38becfbd5e4f739c31fcd9ce44c849f1fad9e4c"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:e589e27971c2a3efff3fadafb16e5aef7ff93250f0134ec4b52052b673cf988d"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:d2ffbc3715a52b037bcb0f6ff524a9367f642cdc5817944f6af5479bbb2eb50e"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_i686.whl", hash = "sha256:cd096e23c6a4f9c819525a437fa0a99d1c67a1b6bb30948d46f33afbc53596cf"}, - {file = "ruff-0.5.0-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:46e193b36f2255729ad34a49c9a997d506e58f08555366b2108783b3064a0e1e"}, - {file = "ruff-0.5.0-py3-none-win32.whl", hash = "sha256:49141d267100f5ceff541b4e06552e98527870eafa1acc9dec9139c9ec5af64c"}, - {file = "ruff-0.5.0-py3-none-win_amd64.whl", hash = "sha256:e9118f60091047444c1b90952736ee7b1792910cab56e9b9a9ac20af94cd0440"}, - {file = "ruff-0.5.0-py3-none-win_arm64.whl", hash = "sha256:ed5c4df5c1fb4518abcb57725b576659542bdbe93366f4f329e8f398c4b71178"}, - {file = "ruff-0.5.0.tar.gz", hash = "sha256:eb641b5873492cf9bd45bc9c5ae5320648218e04386a5f0c264ad6ccce8226a1"}, + {file = "ruff-0.5.1-py3-none-linux_armv6l.whl", hash = "sha256:6ecf968fcf94d942d42b700af18ede94b07521bd188aaf2cd7bc898dd8cb63b6"}, + {file = "ruff-0.5.1-py3-none-macosx_10_12_x86_64.whl", hash = "sha256:204fb0a472f00f2e6280a7c8c7c066e11e20e23a37557d63045bf27a616ba61c"}, + {file = "ruff-0.5.1-py3-none-macosx_11_0_arm64.whl", hash = "sha256:d235968460e8758d1e1297e1de59a38d94102f60cafb4d5382033c324404ee9d"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:38beace10b8d5f9b6bdc91619310af6d63dd2019f3fb2d17a2da26360d7962fa"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5e478d2f09cf06add143cf8c4540ef77b6599191e0c50ed976582f06e588c994"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f0368d765eec8247b8550251c49ebb20554cc4e812f383ff9f5bf0d5d94190b0"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_ppc64.manylinux2014_ppc64.whl", hash = "sha256:3a9a9a1b582e37669b0138b7c1d9d60b9edac880b80eb2baba6d0e566bdeca4d"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bdd9f723e16003623423affabcc0a807a66552ee6a29f90eddad87a40c750b78"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:be9fd62c1e99539da05fcdc1e90d20f74aec1b7a1613463ed77870057cd6bd96"}, + {file = "ruff-0.5.1-py3-none-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e216fc75a80ea1fbd96af94a6233d90190d5b65cc3d5dfacf2bd48c3e067d3e1"}, + {file = "ruff-0.5.1-py3-none-musllinux_1_2_aarch64.whl", hash = "sha256:c4c2112e9883a40967827d5c24803525145e7dab315497fae149764979ac7929"}, + {file = "ruff-0.5.1-py3-none-musllinux_1_2_armv7l.whl", hash = "sha256:dfaf11c8a116394da3b65cd4b36de30d8552fa45b8119b9ef5ca6638ab964fa3"}, + {file = "ruff-0.5.1-py3-none-musllinux_1_2_i686.whl", hash = "sha256:d7ceb9b2fe700ee09a0c6b192c5ef03c56eb82a0514218d8ff700f6ade004108"}, + {file = "ruff-0.5.1-py3-none-musllinux_1_2_x86_64.whl", hash = "sha256:bac6288e82f6296f82ed5285f597713acb2a6ae26618ffc6b429c597b392535c"}, + {file = "ruff-0.5.1-py3-none-win32.whl", hash = "sha256:5c441d9c24ec09e1cb190a04535c5379b36b73c4bc20aa180c54812c27d1cca4"}, + {file = "ruff-0.5.1-py3-none-win_amd64.whl", hash = "sha256:b1789bf2cd3d1b5a7d38397cac1398ddf3ad7f73f4de01b1e913e2abc7dfc51d"}, + {file = "ruff-0.5.1-py3-none-win_arm64.whl", hash = "sha256:2875b7596a740cbbd492f32d24be73e545a4ce0a3daf51e4f4e609962bfd3cd2"}, + {file = "ruff-0.5.1.tar.gz", hash = "sha256:3164488aebd89b1745b47fd00604fb4358d774465f20d1fcd907f9c0fc1b0655"}, ] [[package]] @@ -1421,13 +1421,13 @@ typing = ["mypy (>=1.4)"] [[package]] name = "tenacity" -version = "8.4.2" +version = "8.5.0" description = "Retry code until it succeeds" optional = false python-versions = ">=3.8" files = [ - {file = "tenacity-8.4.2-py3-none-any.whl", hash = "sha256:9e6f7cf7da729125c7437222f8a522279751cdfbe6b67bfe64f75d3a348661b2"}, - {file = "tenacity-8.4.2.tar.gz", hash = "sha256:cd80a53a79336edba8489e767f729e4f391c896956b57140b5d7511a64bbd3ef"}, + {file = "tenacity-8.5.0-py3-none-any.whl", hash = "sha256:b594c2a5945830c267ce6b79a166228323ed52718f30302c1359836112346687"}, + {file = "tenacity-8.5.0.tar.gz", hash = "sha256:8bc6c0c8a09b31e6cad13c47afbed1a567518250a9a171418582ed8d9c20ca78"}, ] [package.extras] @@ -1447,13 +1447,13 @@ files = [ [[package]] name = "types-boltons" -version = "23.1.0.20240331" +version = "24.0.0.20240423" description = "Typing stubs for boltons" optional = false python-versions = ">=3.8" files = [ - {file = "types-boltons-23.1.0.20240331.tar.gz", hash = "sha256:7e95cd94f009f54b6d75e4b96de204287cc43e7f7602ce3702d575345c67bbb1"}, - {file = "types_boltons-23.1.0.20240331-py3-none-any.whl", hash = "sha256:58c1f57aa40b1615d48e2aca776174484f7b963ca5f3e9c6ee4743db8ede50f3"}, + {file = "types-boltons-24.0.0.20240423.tar.gz", hash = "sha256:a0e418f2e1d6b6a561ef441cc14e8b3bf5477cbb307ec27d7f330caca13dd3aa"}, + {file = "types_boltons-24.0.0.20240423-py3-none-any.whl", hash = "sha256:5965274b6123ac6c7d90cae54beb699b83e550e66501b0dfb5dcca4fc53955ab"}, ] [[package]] @@ -1566,4 +1566,4 @@ test = ["big-O", "importlib-resources", "jaraco.functools", "jaraco.itertools", [metadata] lock-version = "2.0" python-versions = ">=3.9" -content-hash = "8171a64e602e81c7a7380f3175f6745129c2ed2464acdb49c5a9d784836839f5" +content-hash = "f698ccbb6ecba2a3182497a16e5d88170a6f04c1c481cfbfd7405342d7e872e5" diff --git a/pyproject.toml b/pyproject.toml index f76b01a..d47b899 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -38,7 +38,7 @@ backports-strenum = {version = ">=1.3.1", python = "<3.11"} [tool.poetry.group.dev.dependencies] ruff = "^0.5.0" mypy = "^1.10.1" -types-boltons = "^23.1.0.20240331" +types-boltons = "^24.0.0.20240423" pytest = "^8.2.2" pytest-asyncio = "^0.23.5.post1" pre-commit = "^3.7.1" @@ -46,7 +46,7 @@ coverage = "^7.5.4" [tool.poetry.group.docs.dependencies] mkdocs-material = "^9.5.28" -mkdocstrings = {extras = ["python"], version = "^0.24.0"} +mkdocstrings = {extras = ["python"], version = "^0.25.1"} mkdocs-autorefs = "^1.0.1" [tool.ruff] diff --git a/src/pyanilist/_types.py b/src/pyanilist/_types.py index f4602d5..abe23ba 100644 --- a/src/pyanilist/_types.py +++ b/src/pyanilist/_types.py @@ -15,7 +15,7 @@ class YearsActive(NamedTuple): """ Simple Named Tuple for - `_models.Staff.years_active` + [`Staff.years_active`][pyanilist._models.Staff.years_active] """ start_year: int | None = None @@ -30,3 +30,4 @@ class YearsActive(NamedTuple): description="8 digit long date integer (YYYYMMDD). Unknown dates represented by 0. E.g. 2016: 20160000, May 1976: 19760500", ), ] +"""8 digit long date integer (YYYYMMDD). Unknown dates represented by 0. E.g. 2016: 20160000, May 1976: 19760500""" \ No newline at end of file From 9dd03d0624b9595a6b62857805b2ef30e7c6f888 Mon Sep 17 00:00:00 2001 From: Raventric <78981416+Ravencentric@users.noreply.github.com> Date: Sat, 6 Jul 2024 09:44:28 +0530 Subject: [PATCH 6/6] fix: async client --- src/pyanilist/_clients/_async.py | 3 +-- tests/test_anilist.py | 2 +- tests/test_async_anilist.py | 2 +- 3 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pyanilist/_clients/_async.py b/src/pyanilist/_clients/_async.py index daf9821..48b03e2 100644 --- a/src/pyanilist/_clients/_async.py +++ b/src/pyanilist/_clients/_async.py @@ -1,6 +1,5 @@ from __future__ import annotations -from collections.abc import Iterable from typing import Any from httpx import AsyncClient, HTTPError, Response @@ -11,7 +10,7 @@ from .._models import Media from .._parser import post_process_response from .._query import query_string -from .._types import FuzzyDateInt +from .._types import FuzzyDateInt, Iterable from .._utils import to_anilist_case diff --git a/tests/test_anilist.py b/tests/test_anilist.py index 42f4461..27779ee 100644 --- a/tests/test_anilist.py +++ b/tests/test_anilist.py @@ -82,7 +82,7 @@ def test_anilist_with_constraints() -> None: season_year=2016, type=MediaType.ANIME, format=MediaFormat.TV, - status=MediaStatus.FINISHED, + status_in=[MediaStatus.FINISHED], ) assert media.title.romaji == "Boku no Hero Academia" assert media.start_date.year == 2016 diff --git a/tests/test_async_anilist.py b/tests/test_async_anilist.py index 35ac332..f20cda9 100644 --- a/tests/test_async_anilist.py +++ b/tests/test_async_anilist.py @@ -82,7 +82,7 @@ async def test_anilist_with_constraints() -> None: season_year=2016, type=MediaType.ANIME, format=MediaFormat.TV, - status=MediaStatus.FINISHED, + status_in=[MediaStatus.FINISHED], ) assert media.title.romaji == "Boku no Hero Academia" assert media.start_date.year == 2016