From 153cc7bef216d258020df2393b26332bb2512804 Mon Sep 17 00:00:00 2001 From: SD Date: Sun, 28 Jan 2024 15:53:07 +0000 Subject: [PATCH 01/14] Improve error messages + add release.md requirements (#3361) * Improve error messages on after and before argument + add release.me requirement to README * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * add tests + refer to contribution page for contributers * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Add working test for the new error messages * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * remove commented out code --------- Co-authored-by: Sascha Dobbelaere Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- README.md | 3 ++- RELEASE.md | 4 +++ strawberry/relay/types.py | 13 ++++++++-- tests/relay/test_fields.py | 50 ++++++++++++++++++++++++++++++++++++++ 4 files changed, 67 insertions(+), 3 deletions(-) create mode 100644 RELEASE.md diff --git a/README.md b/README.md index c0ac81d7f6..195e7aa87a 100644 --- a/README.md +++ b/README.md @@ -122,7 +122,8 @@ poetry install --with integrations poetry run pytest ``` -This will install all the dependencies (including dev ones) and run the tests. +For all further detail, check out the [Contributing Page](CONTRIBUTING.md) + ### Pre commit diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..97a74c8ea6 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,4 @@ +Release type: patch + +- Improved error message when supplying in incorrect before or after argument with using relay and pagination. +- Add extra PR requirement in README.md diff --git a/strawberry/relay/types.py b/strawberry/relay/types.py index 200452c0f4..7510dc642c 100644 --- a/strawberry/relay/types.py +++ b/strawberry/relay/types.py @@ -808,11 +808,20 @@ def resolve_connection( if after: after_type, after_parsed = from_base64(after) - assert after_type == PREFIX + if after_type != PREFIX: + # When the base64 hash doesnt exist, the after_type seems to return + # arrayconnEction instead of PREFIX. Let's raise a predictable + # instead of "An unknown error occurred." + raise TypeError("Argument 'after' contains a non-existing value.") + start = int(after_parsed) + 1 if before: before_type, before_parsed = from_base64(before) - assert before_type == PREFIX + if before_type != PREFIX: + # When the base64 hash doesnt exist, the after_type seems to return + # arrayconnEction instead of PREFIX. Let's raise a predictable + # instead of "An unknown error occurred. + raise TypeError("Argument 'before' contains a non-existing value.") end = int(before_parsed) if isinstance(first, int): diff --git a/tests/relay/test_fields.py b/tests/relay/test_fields.py index 76ceca95b3..0c0cd4722d 100644 --- a/tests/relay/test_fields.py +++ b/tests/relay/test_fields.py @@ -1574,3 +1574,53 @@ class Query: } ''' assert str(schema) == textwrap.dedent(expected).strip() + + +before_after_test_query = """ +query fruitsBeforeAfterTest ( + $before: String = null, + $after: String = null, +) { + fruits ( + before: $before + after: $after + ) { + edges { + cursor + node { + id + } + } + } +} +""" + + +async def test_query_before_error(): + """ + Verify if the error raised on a non-existing before hash + raises the correct error + """ + # with pytest.raises(ValueError): + index = to_base64("Fake", 9292292) + result = await schema.execute( + before_after_test_query, + variable_values={"before": index}, + ) + assert result.errors is not None + assert "Argument 'before' contains a non-existing value" in str(result.errors) + + +def test_query_after_error(): + """ + Verify if the error raised on a non-existing before hash + raises the correct error + """ + index = to_base64("Fake", 9292292) + result = schema.execute_sync( + before_after_test_query, + variable_values={"after": index}, + ) + + assert result.errors is not None + assert "Argument 'after' contains a non-existing value" in str(result.errors) From a8f1a69cda340e68daefec2166fc496698d04369 Mon Sep 17 00:00:00 2001 From: Botberry Date: Sun, 28 Jan 2024 15:53:55 +0000 Subject: [PATCH 02/14] =?UTF-8?q?Release=20=F0=9F=8D=93=200.219.1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 9 +++++++++ RELEASE.md | 4 ---- pyproject.toml | 2 +- 3 files changed, 10 insertions(+), 5 deletions(-) delete mode 100644 RELEASE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index 5517d06f56..7bb025d830 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,15 @@ CHANGELOG ========= +0.219.1 - 2024-01-28 +-------------------- + +- Improved error message when supplying in incorrect before or after argument with using relay and pagination. +- Add extra PR requirement in README.md + +Contributed by [SD](https://github.com/sdobbelaere) via [PR #3361](https://github.com/strawberry-graphql/strawberry/pull/3361/) + + 0.219.0 - 2024-01-24 -------------------- diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 97a74c8ea6..0000000000 --- a/RELEASE.md +++ /dev/null @@ -1,4 +0,0 @@ -Release type: patch - -- Improved error message when supplying in incorrect before or after argument with using relay and pagination. -- Add extra PR requirement in README.md diff --git a/pyproject.toml b/pyproject.toml index b4c8fdb8f5..0eb5655292 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "strawberry-graphql" packages = [ { include = "strawberry" } ] -version = "0.219.0" +version = "0.219.1" description = "A library for creating GraphQL APIs" authors = ["Patrick Arminio "] license = "MIT" From 91d5eba3a238d6710c4a63ad07d8923cee21ce6d Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Mon, 5 Feb 2024 16:28:02 +0100 Subject: [PATCH 03/14] Update changelog with breaking change for permissions (#3371) * Update changelog with breaking change for permissions * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- CHANGELOG.md | 64 ++++++++++++------- docs/breaking-changes/0.159.0.md | 6 +- docs/breaking-changes/0.169.0.md | 9 +-- docs/codegen/query-codegen.md | 6 +- docs/errors/object-is-not-class.md | 3 +- docs/errors/relay-wrong-annotation.md | 21 ++---- .../errors/relay-wrong-resolver-annotation.md | 15 ++--- docs/extensions/_template.md | 3 +- docs/extensions/add-validation-rules.md | 6 +- docs/extensions/mask-errors.md | 3 +- docs/extensions/max-aliases-limiter.md | 3 +- docs/extensions/max-tokens-limiter.md | 3 +- docs/extensions/opentelemetry.md | 3 +- docs/extensions/parser-cache.md | 3 +- docs/extensions/pyinstrument.md | 3 +- docs/extensions/query-depth-limiter.md | 3 +- docs/extensions/validation-cache.md | 3 +- docs/general/schema-basics.md | 9 +-- docs/guides/authentication.md | 3 +- docs/guides/pagination/cursor-based.md | 9 +-- docs/guides/tools.md | 3 +- docs/integrations/asgi.md | 3 +- docs/integrations/channels.md | 3 +- docs/integrations/creating-an-integration.md | 24 +++---- docs/integrations/pydantic.md | 3 +- docs/types/enums.md | 3 +- docs/types/schema.md | 11 ++-- tests/schema/test_permission.py | 32 ++++++++++ 28 files changed, 128 insertions(+), 132 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 7bb025d830..adb004b973 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -137,6 +137,32 @@ class Query: The old way of adding permissions using `permission_classes` is still supported via the automatic addition of a `PermissionExtension` on the field. +### ⚠️ Breaking changes + +Previously the `kwargs` argument keys for the `has_permission` method were +using camel casing (depending on your schema configuration), now they will +always follow the python name defined in your resolvers. + +```python +class IsAuthorized(BasePermission): + message = "User is not authorized" + + def has_permission( + self, source, info, **kwargs: typing.Any + ) -> bool: # pragma: no cover + # kwargs will have a key called "a_key" + # instead of `aKey` + + return False + + +@strawberry.type +class Query: + @strawberry.field(permission_classes=[IsAuthorized]) + def name(self, a_key: str) -> str: # pragma: no cover + return "Erik" +``` + Using the new `PermissionExtension` API, permissions support even more features: #### Silent errors @@ -891,13 +917,11 @@ class Node: @strawberry.type -class Video(Node): - ... +class Video(Node): ... @strawberry.type -class Image(Node): - ... +class Image(Node): ... @strawberry.type @@ -1708,8 +1732,9 @@ if TYPE_CHECKING: @strawberry.type class MyType: @strawberry.field - async def other_type(self) -> Annotated[OtherType, strawberry.lazy("some.module")]: - ... + async def other_type( + self, + ) -> Annotated[OtherType, strawberry.lazy("some.module")]: ... ``` Contributed by [Thiago Bellini Ribeiro](https://github.com/bellini666) via [PR #2744](https://github.com/strawberry-graphql/strawberry/pull/2744/) @@ -2549,8 +2574,7 @@ class UserPydantic(pydantic.BaseModel): @strawberry.experimental.pydantic.type(UserPydantic, all_fields=True) -class User: - ... +class User: ... @strawberry.type @@ -2913,8 +2937,7 @@ class Foo(Generic[T]): @strawberry.type -class IntFoo(Foo[int]): - ... +class IntFoo(Foo[int]): ... @strawberry.type @@ -4017,8 +4040,7 @@ class MyModel(BaseModel): @strawberry.experimental.pydantic.input(model=MyModel, all_fields=True) -class MyModelStrawberry: - ... +class MyModelStrawberry: ... MyModelStrawberry(email="").to_pydantic() @@ -5853,8 +5875,7 @@ class Example(BaseModel): @strawberry.experimental.pydantic.input(model=Example, all_fields=True) -class ExampleGQL: - ... +class ExampleGQL: ... @strawberry.type @@ -6835,13 +6856,11 @@ from strawberry.tools import merge_types @strawberry.type -class QueryA: - ... +class QueryA: ... @strawberry.type -class QueryB: - ... +class QueryB: ... ComboQuery = merge_types("ComboQuery", (QueryB, QueryA)) @@ -7203,8 +7222,7 @@ Word = strawberry.union("Word", types=(Noun, Verb)) @strawberry.field -def add_word(word: Word) -> bool: - ... +def add_word(word: Word) -> bool: ... ``` Contributed by [Mohammad Hossein Yazdani](https://github.com/MAM-SYS) [PR #1222](https://github.com/strawberry-graphql/strawberry/pull/1222/) @@ -7371,8 +7389,7 @@ def name() -> str: MyType = create_type("MyType", [name]) -class Query(MyType): - ... +class Query(MyType): ... ``` Contributed by [Patrick Arminio](https://github.com/patrick91) [PR #1175](https://github.com/strawberry-graphql/strawberry/pull/1175/) @@ -9050,8 +9067,7 @@ class Query: @strawberry.field def user_by_id( id: Annotated[str, strawberry.argument(description="The ID of the user")] - ) -> User: - ... + ) -> User: ... ``` which results in the following schema: diff --git a/docs/breaking-changes/0.159.0.md b/docs/breaking-changes/0.159.0.md index 84b92cf684..78a8aef030 100644 --- a/docs/breaking-changes/0.159.0.md +++ b/docs/breaking-changes/0.159.0.md @@ -15,11 +15,9 @@ The old style hooks are still supported but will be removed in future releases. ```python class MyExtension(Extension): - def on_executing_start(self): - ... + def on_executing_start(self): ... - def on_executing_end(self): - ... + def on_executing_end(self): ... ``` ## After diff --git a/docs/breaking-changes/0.169.0.md b/docs/breaking-changes/0.169.0.md index 4513a5a7c1..a0cef053a9 100644 --- a/docs/breaking-changes/0.169.0.md +++ b/docs/breaking-changes/0.169.0.md @@ -11,12 +11,10 @@ Both `get_root_value` and `get_context` now receive the request as a parameter. If you're customizing these methods you can change the signature to: ```python -def get_root_value(self, request: Request) -> Any: - ... +def get_root_value(self, request: Request) -> Any: ... -def get_context(self, request: Request, response: Response) -> Any: - ... +def get_context(self, request: Request, response: Response) -> Any: ... ``` The same is true for the async version of the view. @@ -29,6 +27,5 @@ async. If you're customizing this method you can change the signature to: ```python -async def get_root_value(self, request: Request) -> Any: - ... +async def get_root_value(self, request: Request) -> Any: ... ``` diff --git a/docs/codegen/query-codegen.md b/docs/codegen/query-codegen.md index 03974ca0db..7fd0585803 100644 --- a/docs/codegen/query-codegen.md +++ b/docs/codegen/query-codegen.md @@ -126,11 +126,9 @@ class QueryCodegenPlugin: """ self.query = query - def on_start(self) -> None: - ... + def on_start(self) -> None: ... - def on_end(self, result: CodegenResult) -> None: - ... + def on_end(self, result: CodegenResult) -> None: ... def generate_code( self, types: List[GraphQLType], operation: GraphQLOperation diff --git a/docs/errors/object-is-not-class.md b/docs/errors/object-is-not-class.md index 02e3406032..901f225910 100644 --- a/docs/errors/object-is-not-class.md +++ b/docs/errors/object-is-not-class.md @@ -14,8 +14,7 @@ import strawberry @strawberry.type -def a_function(): - ... +def a_function(): ... @strawberry.type diff --git a/docs/errors/relay-wrong-annotation.md b/docs/errors/relay-wrong-annotation.md index c7bd2667ed..dd6266ea23 100644 --- a/docs/errors/relay-wrong-annotation.md +++ b/docs/errors/relay-wrong-annotation.md @@ -17,8 +17,7 @@ from strawberry import relay @strawberry.type -class MyType(relay.Node): - ... +class MyType(relay.Node): ... @strawberry.type @@ -28,13 +27,11 @@ class Query: # Missing the Connection class annotation @relay.connection - def my_type_conn_with_resolver(self) -> List[MyType]: - ... + def my_type_conn_with_resolver(self) -> List[MyType]: ... # The connection class is not a subclass of relay.Connection @relay.connection(List[MyType]) - def my_type_conn_with_resolver2(self) -> List[MyType]: - ... + def my_type_conn_with_resolver2(self) -> List[MyType]: ... ``` ## How to fix this error @@ -52,12 +49,10 @@ from strawberry import relay @strawberry.type -class MyType(relay.Node): - ... +class MyType(relay.Node): ... -def get_my_type_list() -> List[MyType]: - ... +def get_my_type_list() -> List[MyType]: ... @strawberry.type @@ -68,11 +63,9 @@ class Query: # Missing the Connection class annotation @relay.connection(relay.Connection[MyType]) - def my_type_conn_with_resolver(self) -> List[MyType]: - ... + def my_type_conn_with_resolver(self) -> List[MyType]: ... # The connection class is not a subclass of relay.Connection @relay.connection(relay.Connection[MyType]) - def my_type_conn_with_resolver2(self) -> List[MyType]: - ... + def my_type_conn_with_resolver2(self) -> List[MyType]: ... ``` diff --git a/docs/errors/relay-wrong-resolver-annotation.md b/docs/errors/relay-wrong-resolver-annotation.md index a03c44e0e0..cba6eb026d 100644 --- a/docs/errors/relay-wrong-resolver-annotation.md +++ b/docs/errors/relay-wrong-resolver-annotation.md @@ -19,19 +19,16 @@ from strawberry import relay @strawberry.type -class MyType(relay.Node): - ... +class MyType(relay.Node): ... @strawberry.type class Query: @relay.connection(relay.Connection[MyType]) - def some_connection_returning_mytype(self) -> MyType: - ... + def some_connection_returning_mytype(self) -> MyType: ... @relay.connection(relay.Connection[MyType]) - def some_connection_returning_any(self) -> Any: - ... + def some_connection_returning_any(self) -> Any: ... ``` This happens because the connection resolver needs to return something that can @@ -60,15 +57,13 @@ from strawberry import relay @strawberry.type -class MyType(relay.Node): - ... +class MyType(relay.Node): ... @strawberry.type class Query: @relay.connection(relay.Connection[MyType]) - def some_connection(self) -> Iterable[MyType]: - ... + def some_connection(self) -> Iterable[MyType]: ... ``` diff --git a/docs/extensions/_template.md b/docs/extensions/_template.md index 568761e48a..be032724ab 100644 --- a/docs/extensions/_template.md +++ b/docs/extensions/_template.md @@ -25,8 +25,7 @@ schema = strawberry.Schema( ## API reference: ```python -class ExtensionName(an_argument=None): - ... +class ExtensionName(an_argument=None): ... ``` #### `an_argument: Optional[str] = None` diff --git a/docs/extensions/add-validation-rules.md b/docs/extensions/add-validation-rules.md index 32b802b885..b7622887d5 100644 --- a/docs/extensions/add-validation-rules.md +++ b/docs/extensions/add-validation-rules.md @@ -18,8 +18,7 @@ from strawberry.extensions import AddValidationRules from graphql import ValidationRule -class MyCustomRule(ValidationRule): - ... +class MyCustomRule(ValidationRule): ... schema = strawberry.Schema( @@ -33,8 +32,7 @@ schema = strawberry.Schema( ## API reference: ```python -class AddValidationRules(validation_rules): - ... +class AddValidationRules(validation_rules): ... ``` #### `validation_rules: List[Type[ASTValidationRule]]` diff --git a/docs/extensions/mask-errors.md b/docs/extensions/mask-errors.md index 7f6910eb90..21491fb3ba 100644 --- a/docs/extensions/mask-errors.md +++ b/docs/extensions/mask-errors.md @@ -28,8 +28,7 @@ schema = strawberry.Schema( ```python class MaskErrors( should_mask_error=default_should_mask_error, error_message="Unexpected error." -): - ... +): ... ``` #### `should_mask_error: Callable[[GraphQLError], bool] = default_should_mask_error` diff --git a/docs/extensions/max-aliases-limiter.md b/docs/extensions/max-aliases-limiter.md index 465244c8b9..f9794bf57c 100644 --- a/docs/extensions/max-aliases-limiter.md +++ b/docs/extensions/max-aliases-limiter.md @@ -25,8 +25,7 @@ schema = strawberry.Schema( ## API reference: ```python -class MaxAliasesLimiter(max_alias_count): - ... +class MaxAliasesLimiter(max_alias_count): ... ``` #### `max_alias_count: int` diff --git a/docs/extensions/max-tokens-limiter.md b/docs/extensions/max-tokens-limiter.md index 530dae3ee9..11e864a6db 100644 --- a/docs/extensions/max-tokens-limiter.md +++ b/docs/extensions/max-tokens-limiter.md @@ -27,8 +27,7 @@ With the above configuration, if a client sends a query with more than 1000 toke ## API reference: ```python -class MaxTokensLimiter(max_token_count): - ... +class MaxTokensLimiter(max_token_count): ... ``` #### `max_token_count: int` diff --git a/docs/extensions/opentelemetry.md b/docs/extensions/opentelemetry.md index 57cb78e2f3..89c2f63377 100644 --- a/docs/extensions/opentelemetry.md +++ b/docs/extensions/opentelemetry.md @@ -55,8 +55,7 @@ schema = strawberry.Schema( ## API reference: ```python -class OpenTelemetryExtension(arg_filter=None): - ... +class OpenTelemetryExtension(arg_filter=None): ... ``` #### `arg_filter: Optional[ArgFilter]` diff --git a/docs/extensions/parser-cache.md b/docs/extensions/parser-cache.md index 61e7370577..a80167157d 100644 --- a/docs/extensions/parser-cache.md +++ b/docs/extensions/parser-cache.md @@ -26,8 +26,7 @@ schema = strawberry.Schema( ## API reference: ```python -class ParserCache(maxsize=None): - ... +class ParserCache(maxsize=None): ... ``` #### `maxsize: Optional[int] = None` diff --git a/docs/extensions/pyinstrument.md b/docs/extensions/pyinstrument.md index ab738700b8..de298671b8 100644 --- a/docs/extensions/pyinstrument.md +++ b/docs/extensions/pyinstrument.md @@ -25,8 +25,7 @@ schema = strawberry.Schema( ## API reference: ```python -class PyInstrument(report_Path=Path("pyinstrument.html")): - ... +class PyInstrument(report_Path=Path("pyinstrument.html")): ... ``` #### `report_path: Path = Path("pyinstrument.html")` diff --git a/docs/extensions/query-depth-limiter.md b/docs/extensions/query-depth-limiter.md index 0182e73fe4..bd32ce94ce 100644 --- a/docs/extensions/query-depth-limiter.md +++ b/docs/extensions/query-depth-limiter.md @@ -25,8 +25,7 @@ schema = strawberry.Schema( ## API reference: ```python -class QueryDepthLimiter(max_depth, callback=None, should_ignore=None): - ... +class QueryDepthLimiter(max_depth, callback=None, should_ignore=None): ... ``` #### `max_depth: int` diff --git a/docs/extensions/validation-cache.md b/docs/extensions/validation-cache.md index 42254fed80..a4cb9739ce 100644 --- a/docs/extensions/validation-cache.md +++ b/docs/extensions/validation-cache.md @@ -25,8 +25,7 @@ schema = strawberry.Schema( ## API reference: ```python -class ValidationCache(maxsize=None): - ... +class ValidationCache(maxsize=None): ... ``` #### `maxsize: Optional[int] = None` diff --git a/docs/general/schema-basics.md b/docs/general/schema-basics.md index bfb5ff4923..fbd4e9b25d 100644 --- a/docs/general/schema-basics.md +++ b/docs/general/schema-basics.md @@ -299,8 +299,7 @@ the following: @strawberry.type class Mutation: @strawberry.field - def add_book(self, title: str, author: str) -> Book: - ... + def add_book(self, title: str, author: str) -> Book: ... ``` This Mutation type defines a single available mutation, `addBook`. The mutation @@ -361,8 +360,7 @@ Consider our previous mutation to add a book: @strawberry.type class Mutation: @strawberry.field - def add_book(self, title: str, author: str) -> Book: - ... + def add_book(self, title: str, author: str) -> Book: ... ``` Instead of accepting two arguments, this mutation could accept a single input @@ -382,8 +380,7 @@ class AddBookInput: @strawberry.type class Mutation: @strawberry.field - def add_book(self, book: AddBookInput) -> Book: - ... + def add_book(self, book: AddBookInput) -> Book: ... ``` Not only does this facilitate passing the AddBookInput type around within our diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md index 557ffd6476..93bd6bc0be 100644 --- a/docs/guides/authentication.md +++ b/docs/guides/authentication.md @@ -69,8 +69,7 @@ from strawberry.types.info import RootValueType @strawberry.type -class User: - ... # This is just a stub for an actual user object +class User: ... # This is just a stub for an actual user object class Context(BaseContext): diff --git a/docs/guides/pagination/cursor-based.md b/docs/guides/pagination/cursor-based.md index 43ebf07e2c..f3358410a2 100644 --- a/docs/guides/pagination/cursor-based.md +++ b/docs/guides/pagination/cursor-based.md @@ -97,8 +97,7 @@ class UserResponse: @strawberry.type class Query: @strawberry.field(description="Get a list of users.") - def get_users(self) -> UserResponse: - ... + def get_users(self) -> UserResponse: ... schema = strawberry.Schema(query=Query) @@ -175,8 +174,7 @@ class UserResponse: @strawberry.type class Query: @strawberry.field(description="Get a list of users.") - def get_users(self) -> UserResponse: - ... + def get_users(self) -> UserResponse: ... schema = strawberry.Schema(query=Query) @@ -287,8 +285,7 @@ class UserResponse: @strawberry.type class Query: @strawberry.field(description="Get a list of users.") - def get_users(self) -> UserResponse: - ... + def get_users(self) -> UserResponse: ... schema = strawberry.Schema(query=Query) diff --git a/docs/guides/tools.md b/docs/guides/tools.md index f519c046de..52fe7d373b 100644 --- a/docs/guides/tools.md +++ b/docs/guides/tools.md @@ -22,8 +22,7 @@ def create_type( description: Optional[str] = None, directives: Optional[Sequence[object]] = (), extend: bool = False, -) -> Type: - ... +) -> Type: ... ``` Example: diff --git a/docs/integrations/asgi.md b/docs/integrations/asgi.md index ab8698a004..92156433ba 100644 --- a/docs/integrations/asgi.md +++ b/docs/integrations/asgi.md @@ -100,8 +100,7 @@ on the response via the context: from starlette.background import BackgroundTask -async def notify_new_flavour(name: str): - ... +async def notify_new_flavour(name: str): ... @strawberry.type diff --git a/docs/integrations/channels.md b/docs/integrations/channels.md index 87a634aa1c..205998fb90 100644 --- a/docs/integrations/channels.md +++ b/docs/integrations/channels.md @@ -678,8 +678,7 @@ async def listen_to_channel( *, timeout: float | None = None, groups: Sequence[str] | None = None -) -> AsyncGenerator[Any, None]: - ... +) -> AsyncGenerator[Any, None]: ... ``` - `type` - The type of the message to wait for, equivalent to `scope['type']` diff --git a/docs/integrations/creating-an-integration.md b/docs/integrations/creating-an-integration.md index 06c2f09e0c..a2be35c3a9 100644 --- a/docs/integrations/creating-an-integration.md +++ b/docs/integrations/creating-an-integration.md @@ -54,13 +54,11 @@ class MyView( async def get_root_value(self, request: Request) -> Optional[RootValue]: return None - def render_graphql_ide(self, request: Request) -> Response: - ... + def render_graphql_ide(self, request: Request) -> Response: ... def create_response( self, response_data: GraphQLHTTPResponse, sub_response: SubResponse - ) -> Response: - ... + ) -> Response: ... ``` The methods above are the bare minimum that you need to implement to create a @@ -76,26 +74,20 @@ from strawberry.http.types import HTTPMethod, QueryParams, FormData class AsyncHTTPRequestAdapter: @property - def query_params(self) -> Mapping[str, Optional[Union[str, List[str]]]]: - ... + def query_params(self) -> Mapping[str, Optional[Union[str, List[str]]]]: ... @property - def method(self) -> HTTPMethod: - ... + def method(self) -> HTTPMethod: ... @property - def headers(self) -> Mapping[str, str]: - ... + def headers(self) -> Mapping[str, str]: ... @property - def content_type(self) -> Optional[str]: - ... + def content_type(self) -> Optional[str]: ... - async def get_body(self) -> Union[bytes, str]: - ... + async def get_body(self) -> Union[bytes, str]: ... - async def get_form_data(self) -> FormData: - ... + async def get_form_data(self) -> FormData: ... ``` This request adapter will be used to get the request data from the request diff --git a/docs/integrations/pydantic.md b/docs/integrations/pydantic.md index 350cb4cb4e..b2e7e67ee1 100644 --- a/docs/integrations/pydantic.md +++ b/docs/integrations/pydantic.md @@ -342,8 +342,7 @@ class Example(BaseModel): @strawberry.experimental.pydantic.type(model=Example, all_fields=True) -class ExampleGQL: - ... +class ExampleGQL: ... MyScalarType = strawberry.scalar( diff --git a/docs/types/enums.md b/docs/types/enums.md index d07c3884a2..cb2e99d216 100644 --- a/docs/types/enums.md +++ b/docs/types/enums.md @@ -19,8 +19,7 @@ First, create a new class for the new type, which extends class Enum: from enum import Enum -class IceCreamFlavour(Enum): - ... +class IceCreamFlavour(Enum): ... ``` Then, list options as variables in that class: diff --git a/docs/types/schema.md b/docs/types/schema.md index f49969cd4e..8330e18239 100644 --- a/docs/types/schema.md +++ b/docs/types/schema.md @@ -30,8 +30,7 @@ schema = strawberry.Schema(Query) ## API reference ```python -class Schema(Query, mutation=None, subscription=None, **kwargs): - ... +class Schema(Query, mutation=None, subscription=None, **kwargs): ... ``` @@ -123,8 +122,9 @@ Override the implementation of the built in scalars. Executes a GraphQL operation against a schema (async) ```python -async def execute(query, variable_values, context_value, root_value, operation_name): - ... +async def execute( + query, variable_values, context_value, root_value, operation_name +): ... ``` #### `query: str` @@ -154,8 +154,7 @@ operation in the document will be executed. Executes a GraphQL operation against a schema ```python -def execute_sync(query, variable_values, context_value, root_value, operation_name): - ... +def execute_sync(query, variable_values, context_value, root_value, operation_name): ... ``` #### `query: str` diff --git a/tests/schema/test_permission.py b/tests/schema/test_permission.py index 6ddf12c7c4..b9853187b4 100644 --- a/tests/schema/test_permission.py +++ b/tests/schema/test_permission.py @@ -560,3 +560,35 @@ def name(self) -> str: # pragma: no cover } """ assert print_schema(schema) == textwrap.dedent(expected_output).strip() + + +def test_basic_permission_access_inputs(): + class IsAuthorized(BasePermission): + message = "User is not authorized" + + def has_permission( + self, source, info, **kwargs: typing.Any + ) -> bool: # pragma: no cover + if kwargs["a_key"] == "secret": + return True + + return False + + @strawberry.type + class Query: + @strawberry.field(permission_classes=[IsAuthorized]) + def name(self, a_key: str) -> str: # pragma: no cover + return "Erik" + + schema = strawberry.Schema(query=Query) + + query = '{ name(aKey: "example") }' + result = schema.execute_sync(query) + + assert result.errors[0].message == "User is not authorized" + + query = '{ name(aKey: "secret") }' + + result = schema.execute_sync(query) + + assert result.data["name"] == "Erik" From 531e37e1acf8f65954c73975e6aeccf5c87bc762 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Mon, 5 Feb 2024 16:30:57 +0100 Subject: [PATCH 04/14] Add deprecation change docs --- docs/breaking-changes.md | 1 + docs/breaking-changes/0.217.0.md | 29 +++++++++++++++++++++++++++++ 2 files changed, 30 insertions(+) create mode 100644 docs/breaking-changes/0.217.0.md diff --git a/docs/breaking-changes.md b/docs/breaking-changes.md index 459c7f91c6..520d2f222e 100644 --- a/docs/breaking-changes.md +++ b/docs/breaking-changes.md @@ -4,6 +4,7 @@ title: List of breaking changes and deprecations # List of breaking changes and deprecations +- [Version 0.217.0 - 18 December 2023](./breaking-changes/0.217.0.md) - [Version 0.213.0 - 8 November 2023](./breaking-changes/0.213.0.md) - [Version 0.180.0 - 31 May 2023](./breaking-changes/0.180.0.md) - [Version 0.169.0 - 5 April 2023](./breaking-changes/0.169.0.md) diff --git a/docs/breaking-changes/0.217.0.md b/docs/breaking-changes/0.217.0.md new file mode 100644 index 0000000000..b76410008c --- /dev/null +++ b/docs/breaking-changes/0.217.0.md @@ -0,0 +1,29 @@ +--- +title: 0.217 Breaking Changes +--- + +# v0.217.0 changes how kwargs are passed to `has_permission` method + +Previously the `kwargs` argument keys for the `has_permission` method were using +camel casing (depending on your schema configuration), now they will always +follow the python name defined in your resolvers. + +```python +class IsAuthorized(BasePermission): + message = "User is not authorized" + + def has_permission( + self, source, info, **kwargs: typing.Any + ) -> bool: # pragma: no cover + # kwargs will have a key called "a_key" + # instead of `aKey` + + return False + + +@strawberry.type +class Query: + @strawberry.field(permission_classes=[IsAuthorized]) + def name(self, a_key: str) -> str: # pragma: no cover + return "Erik" +``` From 6123d62afb2266e68be10215ce914335a97d32c5 Mon Sep 17 00:00:00 2001 From: "pre-commit-ci[bot]" <66853113+pre-commit-ci[bot]@users.noreply.github.com> Date: Mon, 5 Feb 2024 17:41:37 +0100 Subject: [PATCH 05/14] [pre-commit.ci] pre-commit autoupdate (#3270) MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit * [pre-commit.ci] pre-commit autoupdate updates: - [github.com/astral-sh/ruff-pre-commit: v0.1.6 → v0.2.0](https://github.com/astral-sh/ruff-pre-commit/compare/v0.1.6...v0.2.0) - [github.com/pre-commit/mirrors-prettier: v3.1.0 → v4.0.0-alpha.8](https://github.com/pre-commit/mirrors-prettier/compare/v3.1.0...v4.0.0-alpha.8) * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .pre-commit-config.yaml | 4 ++-- strawberry/experimental/pydantic/utils.py | 5 ++--- strawberry/extensions/max_aliases.py | 2 +- strawberry/utils/typing.py | 2 +- tests/aiohttp/test_websockets.py | 10 +++++----- tests/http/test_graphql_ide.py | 2 +- tests/schema/extensions/test_sentry.py | 10 +++++----- 7 files changed, 17 insertions(+), 18 deletions(-) diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index 643af8b7b7..f39cf5911e 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.1.6 + rev: v0.2.0 hooks: - id: ruff-format exclude: ^tests/\w+/snapshots/ @@ -14,7 +14,7 @@ repos: exclude: (CHANGELOG|TWEET).md - repo: https://github.com/pre-commit/mirrors-prettier - rev: v3.1.0 + rev: v4.0.0-alpha.8 hooks: - id: prettier files: '^docs/.*\.mdx?$' diff --git a/strawberry/experimental/pydantic/utils.py b/strawberry/experimental/pydantic/utils.py index 02b2740b71..4f8629a0fc 100644 --- a/strawberry/experimental/pydantic/utils.py +++ b/strawberry/experimental/pydantic/utils.py @@ -6,7 +6,6 @@ Any, List, NamedTuple, - NoReturn, Set, Tuple, Type, @@ -126,7 +125,7 @@ def get_default_factory_for_field( def ensure_all_auto_fields_in_pydantic( model: Type[BaseModel], auto_fields: Set[str], cls_name: str -) -> Union[NoReturn, None]: +) -> None: # Raise error if user defined a strawberry.auto field not present in the model non_existing_fields = list(auto_fields - get_model_fields(model).keys()) @@ -135,4 +134,4 @@ def ensure_all_auto_fields_in_pydantic( fields=non_existing_fields, cls_name=cls_name, model=model ) else: - return None + return diff --git a/strawberry/extensions/max_aliases.py b/strawberry/extensions/max_aliases.py index 1606462c84..77e55dc1f9 100644 --- a/strawberry/extensions/max_aliases.py +++ b/strawberry/extensions/max_aliases.py @@ -65,7 +65,7 @@ def __init__(self, validation_context: ValidationContext): def count_fields_with_alias( - selection_set_owner: Union[ExecutableDefinitionNode, FieldNode, InlineFragmentNode] + selection_set_owner: Union[ExecutableDefinitionNode, FieldNode, InlineFragmentNode], ) -> int: if selection_set_owner.selection_set is None: return 0 diff --git a/strawberry/utils/typing.py b/strawberry/utils/typing.py index debf2bc5e1..f066de3de3 100644 --- a/strawberry/utils/typing.py +++ b/strawberry/utils/typing.py @@ -214,7 +214,7 @@ def _ast_replace_union_operation(expr: ast.Expr) -> ast.Expr: def _ast_replace_union_operation( - expr: Union[ast.Expr, ast.expr] + expr: Union[ast.Expr, ast.expr], ) -> Union[ast.Expr, ast.expr]: if isinstance(expr, ast.Expr) and isinstance( expr.value, (ast.BinOp, ast.Subscript) diff --git a/tests/aiohttp/test_websockets.py b/tests/aiohttp/test_websockets.py index b9bce3457b..82d6a5db00 100644 --- a/tests/aiohttp/test_websockets.py +++ b/tests/aiohttp/test_websockets.py @@ -9,7 +9,7 @@ async def test_turning_off_graphql_ws( - aiohttp_client: Callable[..., Awaitable[TestClient]] + aiohttp_client: Callable[..., Awaitable[TestClient]], ) -> None: from .app import create_app @@ -27,7 +27,7 @@ async def test_turning_off_graphql_ws( async def test_turning_off_graphql_transport_ws( - aiohttp_client: Callable[..., Awaitable[TestClient]] + aiohttp_client: Callable[..., Awaitable[TestClient]], ): from .app import create_app @@ -45,7 +45,7 @@ async def test_turning_off_graphql_transport_ws( async def test_turning_off_all_ws_protocols( - aiohttp_client: Callable[..., Awaitable[TestClient]] + aiohttp_client: Callable[..., Awaitable[TestClient]], ): from .app import create_app @@ -72,7 +72,7 @@ async def test_turning_off_all_ws_protocols( async def test_unsupported_ws_protocol( - aiohttp_client: Callable[..., Awaitable[TestClient]] + aiohttp_client: Callable[..., Awaitable[TestClient]], ): from .app import create_app @@ -90,7 +90,7 @@ async def test_unsupported_ws_protocol( async def test_clients_can_prefer_protocols( - aiohttp_client: Callable[..., Awaitable[TestClient]] + aiohttp_client: Callable[..., Awaitable[TestClient]], ): from .app import create_app diff --git a/tests/http/test_graphql_ide.py b/tests/http/test_graphql_ide.py index 815fc06027..30dfde7c83 100644 --- a/tests/http/test_graphql_ide.py +++ b/tests/http/test_graphql_ide.py @@ -78,7 +78,7 @@ async def test_renders_graphiql_disabled(http_client_class: Type[HttpClient]): async def test_renders_graphiql_disabled_deprecated( - http_client_class: Type[HttpClient] + http_client_class: Type[HttpClient], ): with pytest.deprecated_call( match=r"The `graphiql` argument is deprecated in favor of `graphql_ide`" diff --git a/tests/schema/extensions/test_sentry.py b/tests/schema/extensions/test_sentry.py index 2362a0095c..696818999d 100644 --- a/tests/schema/extensions/test_sentry.py +++ b/tests/schema/extensions/test_sentry.py @@ -163,7 +163,7 @@ async def test_sentry_tracer( @pytest.mark.asyncio async def test_uses_operation_name( - sentry_extension: Tuple[SentryTracingExtension, MagicMock] + sentry_extension: Tuple[SentryTracingExtension, MagicMock], ): extension, mock = sentry_extension @@ -189,7 +189,7 @@ async def test_uses_operation_name( @pytest.mark.asyncio async def test_uses_operation_type( - sentry_extension: Tuple[SentryTracingExtension, MagicMock] + sentry_extension: Tuple[SentryTracingExtension, MagicMock], ): extension, mock = sentry_extension @@ -213,7 +213,7 @@ async def test_uses_operation_type( @pytest.mark.asyncio async def test_uses_operation_subscription( - sentry_extension: Tuple[SentryTracingExtension, MagicMock] + sentry_extension: Tuple[SentryTracingExtension, MagicMock], ): extension, mock = sentry_extension @@ -321,7 +321,7 @@ def test_sentry_tracer_sync( def test_uses_operation_name_sync( - sentry_extension_sync: Tuple[SentryTracingExtensionSync, MagicMock] + sentry_extension_sync: Tuple[SentryTracingExtensionSync, MagicMock], ): extension, mock = sentry_extension_sync @@ -346,7 +346,7 @@ def test_uses_operation_name_sync( def test_uses_operation_type_sync( - sentry_extension_sync: Tuple[SentryTracingExtensionSync, MagicMock] + sentry_extension_sync: Tuple[SentryTracingExtensionSync, MagicMock], ): extension, mock = sentry_extension_sync From af6ae1fc88545912efa90d408308004475cbb7f8 Mon Sep 17 00:00:00 2001 From: Srikanth Date: Tue, 6 Feb 2024 07:22:22 -0800 Subject: [PATCH 06/14] Bumped python-multipart to >=0.0.7 (#3375) * Bumped python-multipart to >=0.0.7 * Bumped python-multipart to >=0.0.7 * Update RELEASE.md * Update ruff and config * Ignore lint issue * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci --------- Co-authored-by: Patrick Arminio Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> --- .github/pyproject.toml | 6 +- .pre-commit-config.yaml | 2 +- .prettierrc | 4 + RELEASE.md | 5 + docs/breaking-changes/0.180.0.md | 25 +- docs/breaking-changes/0.213.0.md | 6 +- docs/codegen/query-codegen.md | 4 +- docs/concepts/async.md | 8 +- docs/editors/vscode.md | 4 +- docs/errors/missing-arguments-annotations.md | 4 +- docs/errors/node-id-annotation.md | 8 +- ...mission-fail-silently-requires-optional.md | 11 +- docs/errors/relay-wrong-annotation.md | 8 +- .../errors/relay-wrong-resolver-annotation.md | 12 +- docs/extensions/add-validation-rules.md | 4 +- docs/extensions/apollo-tracing.md | 7 +- docs/extensions/datadog.md | 3 +- docs/extensions/disable-validation.md | 10 +- docs/extensions/max-aliases-limiter.md | 6 +- docs/extensions/max-tokens-limiter.md | 9 +- docs/extensions/query-depth-limiter.md | 22 +- docs/extensions/sentry-tracing.md | 5 +- docs/extensions/validation-cache.md | 6 +- docs/general/mutations.md | 63 +- docs/general/subscriptions.md | 82 +- docs/general/why.md | 5 +- docs/guides/authentication.md | 23 +- docs/guides/errors.md | 55 +- docs/guides/federation.md | 19 +- docs/guides/field-extensions.md | 77 +- docs/guides/file-upload.md | 21 +- docs/guides/pagination/connections.md | 54 +- docs/guides/pagination/cursor-based.md | 37 +- docs/guides/pagination/offset-based.md | 68 +- docs/guides/pagination/overview.md | 96 +- docs/guides/permissions.md | 68 +- docs/guides/relay.md | 69 +- docs/guides/schema-export.md | 11 +- docs/integrations/aiohttp.md | 4 +- docs/integrations/asgi.md | 4 +- docs/integrations/chalice.md | 10 +- docs/integrations/channels.md | 78 +- docs/integrations/creating-an-integration.md | 4 +- docs/integrations/django.md | 14 +- docs/integrations/fastapi.md | 4 +- docs/integrations/litestar.md | 46 +- docs/integrations/pydantic.md | 24 +- docs/integrations/sanic.md | 4 +- docs/integrations/starlette.md | 6 +- docs/integrations/starlite.md | 4 +- docs/operations/deployment.md | 29 +- docs/operations/testing.md | 36 +- docs/operations/tracing.md | 3 +- docs/types/exceptions.md | 8 +- docs/types/object-types.md | 23 +- docs/types/private.md | 15 +- docs/types/resolvers.md | 6 +- docs/types/scalars.md | 41 +- docs/types/schema-configurations.md | 13 +- docs/types/union.md | 27 +- poetry.lock | 1061 +++++++++-------- pyproject.toml | 60 +- strawberry/utils/aio.py | 2 +- 63 files changed, 1345 insertions(+), 1108 deletions(-) create mode 100644 .prettierrc create mode 100644 RELEASE.md diff --git a/.github/pyproject.toml b/.github/pyproject.toml index cc0cf13d81..511638f2f3 100644 --- a/.github/pyproject.toml +++ b/.github/pyproject.toml @@ -1,5 +1,5 @@ [tool.ruff] extend = "../pyproject.toml" -extend-ignore = [ - "T201", -] + +[tool.ruff.lint] +extend-ignore = ["T201"] diff --git a/.pre-commit-config.yaml b/.pre-commit-config.yaml index f39cf5911e..074cabe31f 100644 --- a/.pre-commit-config.yaml +++ b/.pre-commit-config.yaml @@ -1,6 +1,6 @@ repos: - repo: https://github.com/astral-sh/ruff-pre-commit - rev: v0.2.0 + rev: v0.2.1 hooks: - id: ruff-format exclude: ^tests/\w+/snapshots/ diff --git a/.prettierrc b/.prettierrc new file mode 100644 index 0000000000..cfae7e2e9b --- /dev/null +++ b/.prettierrc @@ -0,0 +1,4 @@ +{ + "proseWrap": "always", + "printWidth": 80 +} diff --git a/RELEASE.md b/RELEASE.md new file mode 100644 index 0000000000..6db8a30af0 --- /dev/null +++ b/RELEASE.md @@ -0,0 +1,5 @@ +Release type: patch + +This releases updates the dependency of `python-multipart` to be at least `0.0.7` (which includes a security fix). + +It also removes the upper bound for `python-multipart` so you can always install the latest version (if compatible) 😊 diff --git a/docs/breaking-changes/0.180.0.md b/docs/breaking-changes/0.180.0.md index 262348a1c6..2b9e80f46b 100644 --- a/docs/breaking-changes/0.180.0.md +++ b/docs/breaking-changes/0.180.0.md @@ -4,18 +4,19 @@ title: 0.180.0 Breaking changes # v0.180.0 introduces a breaking change for the Django Channels HTTP integration -The context object is now a `dict`. This means that you should access the context -value using the `["key"]` syntax instead of the `.key` syntax. +The context object is now a `dict`. This means that you should access the +context value using the `["key"]` syntax instead of the `.key` syntax. -For the HTTP integration, there is also no `ws` key anymore and `request` is a custom -request object containing the full request instead of a `GraphQLHTTPConsumer` instance. -If you need to access the `GraphQLHTTPConsumer` instance in a HTTP connection, you can -access it via `info.context["request"].consumer`. +For the HTTP integration, there is also no `ws` key anymore and `request` is a +custom request object containing the full request instead of a +`GraphQLHTTPConsumer` instance. If you need to access the `GraphQLHTTPConsumer` +instance in a HTTP connection, you can access it via +`info.context["request"].consumer`. -For the WebSockets integration, the context keys did not change, e.g. the values for -`info.context["ws"]`, `info.context["request"]` and `info.context["connection_params"]` -are the same as before. +For the WebSockets integration, the context keys did not change, e.g. the values +for `info.context["ws"]`, `info.context["request"]` and +`info.context["connection_params"]` are the same as before. -If you still want to use the `.key` syntax, you can override `get_context()` -to return a custom dataclass there. See the Channels integration documentation -for an example. +If you still want to use the `.key` syntax, you can override `get_context()` to +return a custom dataclass there. See the Channels integration documentation for +an example. diff --git a/docs/breaking-changes/0.213.0.md b/docs/breaking-changes/0.213.0.md index 54e9f5a4ba..f31f4d6f86 100644 --- a/docs/breaking-changes/0.213.0.md +++ b/docs/breaking-changes/0.213.0.md @@ -5,9 +5,11 @@ title: 0.213.0 Deprecation # v0.213.0 introduces a deprecation for `graphiql` parameter All HTTP integration now will use `graphql_ide` instead of `graphiql` parameter. -If you're not using the `graphiql` parameter, you can safely ignore this deprecation. +If you're not using the `graphiql` parameter, you can safely ignore this +deprecation. -If you're using the `graphiql` parameter, you should change it to `graphql_ide` instead. +If you're using the `graphiql` parameter, you should change it to `graphql_ide` +instead. Here's an example of the changes: diff --git a/docs/codegen/query-codegen.md b/docs/codegen/query-codegen.md index 7fd0585803..3da8e098e7 100644 --- a/docs/codegen/query-codegen.md +++ b/docs/codegen/query-codegen.md @@ -145,8 +145,8 @@ class QueryCodegenPlugin: ### Console plugin -There is also a plugin that helps to orchestrate the codegen process and notify the -user about what the current codegen process is doing. +There is also a plugin that helps to orchestrate the codegen process and notify +the user about what the current codegen process is doing. The interface for the ConsolePlugin looks like: diff --git a/docs/concepts/async.md b/docs/concepts/async.md index 5701371bda..7c1a321ed3 100644 --- a/docs/concepts/async.md +++ b/docs/concepts/async.md @@ -4,12 +4,12 @@ title: Async # Async -Async is a concurrent programming design that has been supported in Python -since version 3.4. To learn more about async in Python refer to +Async is a concurrent programming design that has been supported in Python since +version 3.4. To learn more about async in Python refer to [Real Python’s Async walkthrough](https://realpython.com/async-io-python/). -Strawberry supports both async and non async resolvers, so you can mix and -match them in your code. Here’s an example of an async resolver: +Strawberry supports both async and non async resolvers, so you can mix and match +them in your code. Here’s an example of an async resolver: ```python import asyncio diff --git a/docs/editors/vscode.md b/docs/editors/vscode.md index fb51ae9a8e..1b6a36f5f7 100644 --- a/docs/editors/vscode.md +++ b/docs/editors/vscode.md @@ -7,8 +7,8 @@ title: Visual studio code Strawberry comes with support for both MyPy and Pylance, Microsoft's own language server for Python. -This guide will explain how to configure Visual Studio Code and Pylance to -work with Strawberry. +This guide will explain how to configure Visual Studio Code and Pylance to work +with Strawberry. ## Install Pylance diff --git a/docs/errors/missing-arguments-annotations.md b/docs/errors/missing-arguments-annotations.md index 10179849eb..04c5fe328b 100644 --- a/docs/errors/missing-arguments-annotations.md +++ b/docs/errors/missing-arguments-annotations.md @@ -23,8 +23,8 @@ class Query: schema = strawberry.Schema(query=Query) ``` -This happens because Strawberry needs to know the type of every argument to be able to -generate the correct GraphQL type. +This happens because Strawberry needs to know the type of every argument to be +able to generate the correct GraphQL type. ## How to fix this error diff --git a/docs/errors/node-id-annotation.md b/docs/errors/node-id-annotation.md index e811956769..d7237f25eb 100644 --- a/docs/errors/node-id-annotation.md +++ b/docs/errors/node-id-annotation.md @@ -6,8 +6,8 @@ title: Node ID annotation error ## Description -This error is thrown when a `relay.Node` implemented type can't resolve its -`id` field, due to it being missing or multiple annotated fields being found. +This error is thrown when a `relay.Node` implemented type can't resolve its `id` +field, due to it being missing or multiple annotated fields being found. The following code will throw this error: @@ -25,8 +25,8 @@ class Fruit(relay.Node): This happens because `relay.Node` don't know which field should be used to resolve to generate its `GlobalID` field. -The following would also throw this errors because multiple candidates -were found: +The following would also throw this errors because multiple candidates were +found: ```python import strawberry diff --git a/docs/errors/permission-fail-silently-requires-optional.md b/docs/errors/permission-fail-silently-requires-optional.md index 22633f8ff6..96fee24207 100644 --- a/docs/errors/permission-fail-silently-requires-optional.md +++ b/docs/errors/permission-fail-silently-requires-optional.md @@ -6,8 +6,8 @@ title: Using silent permissions on optional fields ## Description -This error is thrown when a permission extension is configured to use silent permissions on a field that is -required and not a list: +This error is thrown when a permission extension is configured to use silent +permissions on a field that is required and not a list: ```python import strawberry @@ -28,9 +28,10 @@ class Query: schema = strawberry.Schema(query=Query) ``` -This happens because fail_silently is suppsed to hide the field from a user without an error in case of no permissions. -However, non-nullable fields always raise an error when they are set to null. -The only exception to that is a list, because an empty list can be returned. +This happens because fail_silently is suppsed to hide the field from a user +without an error in case of no permissions. However, non-nullable fields always +raise an error when they are set to null. The only exception to that is a list, +because an empty list can be returned. ## How to fix this error diff --git a/docs/errors/relay-wrong-annotation.md b/docs/errors/relay-wrong-annotation.md index dd6266ea23..95b39c1f27 100644 --- a/docs/errors/relay-wrong-annotation.md +++ b/docs/errors/relay-wrong-annotation.md @@ -6,8 +6,8 @@ title: Relay wrong annotation Error ## Description -This error is thrown when a field on a relay connection has a wrong -type annotation. For example, the following code will throw this error: +This error is thrown when a field on a relay connection has a wrong type +annotation. For example, the following code will throw this error: ```python from typing import List @@ -36,8 +36,8 @@ class Query: ## How to fix this error -You can fix this error by properly annotating your attribute or resolver -with `relay.Connection` type subclass. +You can fix this error by properly annotating your attribute or resolver with +`relay.Connection` type subclass. For example: diff --git a/docs/errors/relay-wrong-resolver-annotation.md b/docs/errors/relay-wrong-resolver-annotation.md index cba6eb026d..070a1c61cb 100644 --- a/docs/errors/relay-wrong-resolver-annotation.md +++ b/docs/errors/relay-wrong-resolver-annotation.md @@ -6,8 +6,8 @@ title: Relay wrong resolver annotation Error ## Description -This error is thrown when a field on a relay connection was defined with -a resolver that returns something that is not compatible with pagination. +This error is thrown when a field on a relay connection was defined with a +resolver that returns something that is not compatible with pagination. For example, the following code would throw this error: @@ -68,9 +68,9 @@ class Query: -Note that if you are returning a type different than the connection type, -you will need to subclass the connection type and override its -`resolve_node` method to convert it to the correct type, as explained in -the [relay guide](../guides/relay). +Note that if you are returning a type different than the connection type, you +will need to subclass the connection type and override its `resolve_node` method +to convert it to the correct type, as explained in the +[relay guide](../guides/relay). diff --git a/docs/extensions/add-validation-rules.md b/docs/extensions/add-validation-rules.md index b7622887d5..7bc785551c 100644 --- a/docs/extensions/add-validation-rules.md +++ b/docs/extensions/add-validation-rules.md @@ -8,7 +8,9 @@ tags: validation,security This extension allows you add custom validation rules. -See [graphql.validation.rules.custom](https://github.com/graphql-python/graphql-core/tree/main/src/graphql/validation/rules/custom) for some custom rules that can be added from GraphQl-core. +See +[graphql.validation.rules.custom](https://github.com/graphql-python/graphql-core/tree/main/src/graphql/validation/rules/custom) +for some custom rules that can be added from GraphQl-core. ## Usage example: diff --git a/docs/extensions/apollo-tracing.md b/docs/extensions/apollo-tracing.md index a29fc51a90..89f1254d0f 100644 --- a/docs/extensions/apollo-tracing.md +++ b/docs/extensions/apollo-tracing.md @@ -6,7 +6,9 @@ tags: tracing # `ApolloTracingExtension` -This extension adds [tracing information](https://github.com/apollographql/apollo-tracing) to your response for [Apollo Engine](https://www.apollographql.com/platform/). +This extension adds +[tracing information](https://github.com/apollographql/apollo-tracing) to your +response for [Apollo Engine](https://www.apollographql.com/platform/). ## Usage example: @@ -24,7 +26,8 @@ schema = strawberry.Schema( -If you are not running in an Async context then you'll need to use the sync version: +If you are not running in an Async context then you'll need to use the sync +version: ```python import strawberry diff --git a/docs/extensions/datadog.md b/docs/extensions/datadog.md index 3c77c52edd..0618cba1be 100644 --- a/docs/extensions/datadog.md +++ b/docs/extensions/datadog.md @@ -59,7 +59,8 @@ _No arguments_ ### Overriding the `create_span` method -You can customize any of the spans or add tags to them by overriding the `create_span` method. +You can customize any of the spans or add tags to them by overriding the +`create_span` method. Example: diff --git a/docs/extensions/disable-validation.md b/docs/extensions/disable-validation.md index 4b2ecc7711..1708ebded9 100644 --- a/docs/extensions/disable-validation.md +++ b/docs/extensions/disable-validation.md @@ -6,13 +6,15 @@ tags: performance,validation # `DisableValidation` -This extensions disables all query validation. This can be useful to improve performance in some specific cases, for example when dealing with internal APIs where queries can be trusted. +This extensions disables all query validation. This can be useful to improve +performance in some specific cases, for example when dealing with internal APIs +where queries can be trusted. -Only do this if you know what you are doing! Disabling validation breaks the safety of having typed schema. If you are trying to -improve performance you might want to consider using the -[ValidationCache](./validation-cache) instead. +Only do this if you know what you are doing! Disabling validation breaks the +safety of having typed schema. If you are trying to improve performance you +might want to consider using the [ValidationCache](./validation-cache) instead. diff --git a/docs/extensions/max-aliases-limiter.md b/docs/extensions/max-aliases-limiter.md index f9794bf57c..5fc8140d14 100644 --- a/docs/extensions/max-aliases-limiter.md +++ b/docs/extensions/max-aliases-limiter.md @@ -1,12 +1,14 @@ --- title: MaxAliasesLimiter -summary: Add a validator to limit the maximum number of aliases in a GraphQL document. +summary: + Add a validator to limit the maximum number of aliases in a GraphQL document. tags: security --- # `MaxAliasesLimiter` -This extension adds a validator to limit the maximum number of aliases in a GraphQL document. +This extension adds a validator to limit the maximum number of aliases in a +GraphQL document. ## Usage example: diff --git a/docs/extensions/max-tokens-limiter.md b/docs/extensions/max-tokens-limiter.md index 11e864a6db..f06d82a1e6 100644 --- a/docs/extensions/max-tokens-limiter.md +++ b/docs/extensions/max-tokens-limiter.md @@ -1,12 +1,14 @@ --- title: MaxTokensLimiter -summary: Add a validator to limit the maximum number of tokens in a GraphQL document. +summary: + Add a validator to limit the maximum number of tokens in a GraphQL document. tags: security --- # `MaxTokensLimiter` -This extension adds a validator to limit the maximum number of tokens in a GraphQL document sent to the server. +This extension adds a validator to limit the maximum number of tokens in a +GraphQL document sent to the server. ## Usage example: @@ -22,7 +24,8 @@ schema = strawberry.Schema( ) ``` -With the above configuration, if a client sends a query with more than 1000 tokens, the server will respond with an error message. +With the above configuration, if a client sends a query with more than 1000 +tokens, the server will respond with an error message. ## API reference: diff --git a/docs/extensions/query-depth-limiter.md b/docs/extensions/query-depth-limiter.md index bd32ce94ce..2fd806c9ad 100644 --- a/docs/extensions/query-depth-limiter.md +++ b/docs/extensions/query-depth-limiter.md @@ -34,26 +34,30 @@ The maximum allowed depth for any operation in a GraphQL document. #### `callback: Optional[Callable[[Dict[str, int]], None]` -Called each time validation runs. Receives a dictionary which is a -map of the depths for each operation. +Called each time validation runs. Receives a dictionary which is a map of the +depths for each operation. #### `should_ignore: Optional[Callable[[IgnoreContext], bool]]` Called at each field to determine whether the field should be ignored or not. -Must be implemented by the user and returns `True` if the field should be ignored -and `False` otherwise. +Must be implemented by the user and returns `True` if the field should be +ignored and `False` otherwise. The `IgnoreContext` class has the following attributes: - `field_name` of type `str`: the name of the field to be compared against -- `field_args` of type `strawberry.extensions.query_depth_limiter.FieldArgumentsType`: the arguments of the field to be compared against +- `field_args` of type + `strawberry.extensions.query_depth_limiter.FieldArgumentsType`: the arguments + of the field to be compared against - `query` of type `graphql.language.Node`: the query string -- `context` of type `graphql.validation.ValidationContext`: the context passed to the query +- `context` of type `graphql.validation.ValidationContext`: the context passed + to the query -This argument is injected, regardless of name, by the `QueryDepthLimiter` class and should not be passed by the user. +This argument is injected, regardless of name, by the `QueryDepthLimiter` class +and should not be passed by the user. -Instead, the user should write business logic to determine whether a field should be ignored or not by -the attributes of the `IgnoreContext` class. +Instead, the user should write business logic to determine whether a field +should be ignored or not by the attributes of the `IgnoreContext` class. ## Example with field_name: diff --git a/docs/extensions/sentry-tracing.md b/docs/extensions/sentry-tracing.md index 5e90078f07..d9eedb050a 100644 --- a/docs/extensions/sentry-tracing.md +++ b/docs/extensions/sentry-tracing.md @@ -6,8 +6,9 @@ tags: tracing -As of Sentry 1.32.0, Strawberry is now supported by default. This extension is no longer necessary. -For more details, please refer to the [release notes](https://github.com/getsentry/sentry-python/releases/tag/1.32.0). +As of Sentry 1.32.0, Strawberry is now supported by default. This extension is +no longer necessary. For more details, please refer to the +[release notes](https://github.com/getsentry/sentry-python/releases/tag/1.32.0). Below is the revised usage example: diff --git a/docs/extensions/validation-cache.md b/docs/extensions/validation-cache.md index a4cb9739ce..0f4c7b34fc 100644 --- a/docs/extensions/validation-cache.md +++ b/docs/extensions/validation-cache.md @@ -6,7 +6,8 @@ tags: performance,caching,validation # `ValidationCache` -This extension adds LRU caching to the validation step of query execution to improve performance by caching the validation errors in memory. +This extension adds LRU caching to the validation step of query execution to +improve performance by caching the validation errors in memory. ## Usage example: @@ -30,7 +31,8 @@ class ValidationCache(maxsize=None): ... #### `maxsize: Optional[int] = None` -Set the maxsize of the cache. If `maxsize` is set to `None` then the cache will grow without bound. +Set the maxsize of the cache. If `maxsize` is set to `None` then the cache will +grow without bound. More info: https://docs.python.org/3/library/functools.html#functools.lru_cache diff --git a/docs/general/mutations.md b/docs/general/mutations.md index 178434f367..bd6923e74a 100644 --- a/docs/general/mutations.md +++ b/docs/general/mutations.md @@ -4,15 +4,15 @@ title: Mutations # Mutations -As opposed to queries, mutations in GraphQL represent operations that modify server-side -data and/or cause side effects on the server. For example, you can have a mutation that -creates a new instance in your application or a mutation that sends an email. Like in -queries, they accept parameters and can return anything a regular field can, including -new types and existing object types. This can be useful for fetching the new state of an -object after an update. +As opposed to queries, mutations in GraphQL represent operations that modify +server-side data and/or cause side effects on the server. For example, you can +have a mutation that creates a new instance in your application or a mutation +that sends an email. Like in queries, they accept parameters and can return +anything a regular field can, including new types and existing object types. +This can be useful for fetching the new state of an object after an update. -Let's improve our books project from the [Getting started tutorial](../index.md) and -implement a mutation that is supposed to add a book: +Let's improve our books project from the [Getting started tutorial](../index.md) +and implement a mutation that is supposed to add a book: ```python import strawberry @@ -40,10 +40,11 @@ schema = strawberry.Schema(query=Query, mutation=Mutation) ``` Like queries, mutations are defined in a class that is then passed to the Schema -function. Here we create an `addBook` mutation that accepts a title and an author and -returns a `Book` type. +function. Here we create an `addBook` mutation that accepts a title and an +author and returns a `Book` type. -We would send the following GraphQL document to our server to execute the mutation: +We would send the following GraphQL document to our server to execute the +mutation: ```graphql mutation { @@ -53,13 +54,14 @@ mutation { } ``` -The `addBook` mutation is a simplified example. In a real-world application mutations -will often need to handle errors and communicate those errors back to the client. For -example we might want to return an error if the book already exists. +The `addBook` mutation is a simplified example. In a real-world application +mutations will often need to handle errors and communicate those errors back to +the client. For example we might want to return an error if the book already +exists. You can checkout our documentation on -[dealing with errors](/docs/guides/errors#expected-errors) to learn how to return a -union of types from a mutation. +[dealing with errors](/docs/guides/errors#expected-errors) to learn how to +return a union of types from a mutation. ## Mutations without returned data @@ -81,17 +83,18 @@ type Mutation { -Mutations with void-result go against [this community-created guide on GQL best practices](https://graphql-rules.com/rules/mutation-payload). +Mutations with void-result go against +[this community-created guide on GQL best practices](https://graphql-rules.com/rules/mutation-payload). ### The Input Mutation Extension -It is usually useful to use a pattern of defining a mutation that receives a single -[input type](./input-types) argument called `input`. +It is usually useful to use a pattern of defining a mutation that receives a +single [input type](./input-types) argument called `input`. -Strawberry provides a helper to create a mutation that automatically -creates an input type for you, whose attributes are the same as the args in the resolver. +Strawberry provides a helper to create a mutation that automatically creates an +input type for you, whose attributes are the same as the args in the resolver. For example, suppose we want the mutation defined in the section above to be an input mutation. We can add the `InputMutationExtension` to the field like this: @@ -137,7 +140,9 @@ type Mutation { ## Nested mutations -To avoid a graph becoming too large and to improve discoverability, it can be helpful to group mutations in a namespace, as described by [Apollo's guide on Namespacing by separation of concerns](https://www.apollographql.com/docs/technotes/TN0012-namespacing-by-separation-of-concern/). +To avoid a graph becoming too large and to improve discoverability, it can be +helpful to group mutations in a namespace, as described by +[Apollo's guide on Namespacing by separation of concerns](https://www.apollographql.com/docs/technotes/TN0012-namespacing-by-separation-of-concern/). ```graphql type Mutation { @@ -150,7 +155,9 @@ type FruitMutations { } ``` -Since all GraphQL operations are fields, we can define a `FruitMutation` type and add mutation fields to it like we could add mutation fields to the root `Mutation` type. +Since all GraphQL operations are fields, we can define a `FruitMutation` type +and add mutation fields to it like we could add mutation fields to the root +`Mutation` type. ```python import strawberry @@ -177,8 +184,9 @@ class Mutation: Fields on the root `Mutation` type are resolved serially. Namespace types introduce the potential for mutations to be resolved asynchronously and in parallel because the mutation fields that mutate data are no longer at the root level. -To guarantee serial execution when namespace types are used, clients should use aliases to select the root mutation field for each mutation. -In the following example, once `addFruit` execution is complete, `updateFruitWeight` begins. +To guarantee serial execution when namespace types are used, clients should use +aliases to select the root mutation field for each mutation. In the following +example, once `addFruit` execution is complete, `updateFruitWeight` begins. ```graphql mutation ( @@ -199,5 +207,8 @@ mutation ( } ``` -For more details, see [Apollo's guide on Namespaces for serial mutations](https://www.apollographql.com/docs/technotes/TN0012-namespacing-by-separation-of-concern/#namespaces-for-serial-mutations) and [Rapid API's Interactive Guide to GraphQL Queries: Aliases and Variables](https://rapidapi.com/guides/graphql-aliases-variables). +For more details, see +[Apollo's guide on Namespaces for serial mutations](https://www.apollographql.com/docs/technotes/TN0012-namespacing-by-separation-of-concern/#namespaces-for-serial-mutations) +and +[Rapid API's Interactive Guide to GraphQL Queries: Aliases and Variables](https://rapidapi.com/guides/graphql-aliases-variables). diff --git a/docs/general/subscriptions.md b/docs/general/subscriptions.md index 09f3face01..6879ed5978 100644 --- a/docs/general/subscriptions.md +++ b/docs/general/subscriptions.md @@ -42,9 +42,10 @@ from 0 to the target sleeping between each loop iteration. -The return type of `count` is `AsyncGenerator` where the first generic -argument is the actual type of the response, in most cases the second argument -should be left as `None` (more about Generator typing [here](https://docs.python.org/3/library/typing.html#typing.AsyncGenerator)). +The return type of `count` is `AsyncGenerator` where the first generic argument +is the actual type of the response, in most cases the second argument should be +left as `None` (more about Generator typing +[here](https://docs.python.org/3/library/typing.html#typing.AsyncGenerator)). @@ -67,23 +68,27 @@ demonstrated here. ## Authenticating Subscriptions -Without going into detail on [why](https://github.com/websockets/ws/issues/467), custom headers cannot be set on websocket -requests that originate in browsers. -Therefore, when making any GraphQL requests that rely on a websocket connection, header-based authentication is impossible. +Without going into detail on [why](https://github.com/websockets/ws/issues/467), +custom headers cannot be set on websocket requests that originate in browsers. +Therefore, when making any GraphQL requests that rely on a websocket connection, +header-based authentication is impossible. -Other popular GraphQL solutions, like Apollo for example, -implement functionality to pass information from the client to the server at the point of websocket -connection initialisation. In this way, information that is relevant to the websocket connection -initialisation and to the lifetime of the connection overall -can be passed to the server before any data is streamed back by the server. As such, it is not limited to only authentication credentials! +Other popular GraphQL solutions, like Apollo for example, implement +functionality to pass information from the client to the server at the point of +websocket connection initialisation. In this way, information that is relevant +to the websocket connection initialisation and to the lifetime of the connection +overall can be passed to the server before any data is streamed back by the +server. As such, it is not limited to only authentication credentials! Strawberry's implementation follows that of Apollo's, which as documentation for [client](https://www.apollographql.com/docs/react/data/subscriptions/#5-authenticate-over-websocket-optional) -and [server](https://www.apollographql.com/docs/apollo-server/data/subscriptions/#operation-context) -implementations, by reading the contents of the initial -websocket connection message into the `info.context` object. +and +[server](https://www.apollographql.com/docs/apollo-server/data/subscriptions/#operation-context) +implementations, by reading the contents of the initial websocket connection +message into the `info.context` object. -With Apollo-client as an example of how to send this initial connection information, one defines a `ws-link` as: +With Apollo-client as an example of how to send this initial connection +information, one defines a `ws-link` as: ```javascript import { GraphQLWsLink } from "@apollo/client/link/subscriptions"; @@ -99,8 +104,9 @@ const wsLink = new GraphQLWsLink( ); ``` -and then, upon the establishment of the Susbcription request and underlying websocket connection, -Strawberry injects this `connectionParams` object as follows: +and then, upon the establishment of the Susbcription request and underlying +websocket connection, Strawberry injects this `connectionParams` object as +follows: ```python import asyncio @@ -137,10 +143,11 @@ class Subscription: schema = strawberry.Schema(query=Query, subscription=Subscription) ``` -Strawberry expects the `connection_params` object to be any type, so the client is free to send -any valid JSON object as the initial message of the websocket connection, which is abstracted -as `connectionParams` in Apollo-client, and it will be successfully -injected into the `info.context` object. It is then up to you to handle it correctly! +Strawberry expects the `connection_params` object to be any type, so the client +is free to send any valid JSON object as the initial message of the websocket +connection, which is abstracted as `connectionParams` in Apollo-client, and it +will be successfully injected into the `info.context` object. It is then up to +you to handle it correctly! ## Advanced Subscription Patterns @@ -154,9 +161,9 @@ Both of these types are documented in [PEP-525][pep-525]. Anything yielded from these types of resolvers will be shipped across the websocket. Care needs to be taken to ensure the returned values conform to the GraphQL schema. -The benefit of an AsyncGenerator, over an iterator, is that the complex -business logic can be broken out into a separate module within your codebase. -Allowing you to keep the resolver logic succinct. +The benefit of an AsyncGenerator, over an iterator, is that the complex business +logic can be broken out into a separate module within your codebase. Allowing +you to keep the resolver logic succinct. The following example is similar to the one above, except it returns an AsyncGenerator to the ASGI server which is responsible for streaming @@ -256,9 +263,9 @@ sub-protocols. -The `graphql-transport-ws` protocols repository is called `graphql-ws`. -However, `graphql-ws` is also the name of the legacy protocol. -This documentation always refers to the protocol names. +The `graphql-transport-ws` protocols repository is called `graphql-ws`. However, +`graphql-ws` is also the name of the legacy protocol. This documentation always +refers to the protocol names. @@ -324,8 +331,8 @@ application = GraphQLProtocolTypeRouter( ) ``` -Note: Check the [channels integraton](/docs/integrations/channels.md) page for more information -regarding it. +Note: Check the [channels integraton](/docs/integrations/channels.md) page for +more information regarding it. #### FastAPI @@ -348,12 +355,15 @@ app.include_router(graphql_router, prefix="/graphql") ### Single result operations -In addition to _streaming operations_ (i.e. subscriptions), -the `graphql-transport-ws` protocol supports so called _single result operations_ (i.e. queries and mutations). +In addition to _streaming operations_ (i.e. subscriptions), the +`graphql-transport-ws` protocol supports so called _single result operations_ +(i.e. queries and mutations). -This enables clients to use one protocol and one connection for queries, mutations and subscriptions. -Take a look at the [protocols repository](https://github.com/enisdenjo/graphql-ws) -to learn how to correctly set up the graphql client of your choice. +This enables clients to use one protocol and one connection for queries, +mutations and subscriptions. Take a look at the +[protocols repository](https://github.com/enisdenjo/graphql-ws) to learn how to +correctly set up the graphql client of your choice. -Strawberry supports single result operations out of the box when the `graphql-transport-ws` protocol is enabled. -Single result operations are normal queries and mutations, so there is no need to adjust any resolvers. +Strawberry supports single result operations out of the box when the +`graphql-transport-ws` protocol is enabled. Single result operations are normal +queries and mutations, so there is no need to adjust any resolvers. diff --git a/docs/general/why.md b/docs/general/why.md index cda08ebf13..12a73462aa 100644 --- a/docs/general/why.md +++ b/docs/general/why.md @@ -15,9 +15,8 @@ community with people using GraphQL in Python. -At the moment Strawberry is still in early development, so there's a -chance of things suddenly changing, but hopefully the public API is stable -enough. +At the moment Strawberry is still in early development, so there's a chance of +things suddenly changing, but hopefully the public API is stable enough. diff --git a/docs/guides/authentication.md b/docs/guides/authentication.md index 93bd6bc0be..4aa3188b90 100644 --- a/docs/guides/authentication.md +++ b/docs/guides/authentication.md @@ -4,18 +4,20 @@ title: Authentication # Authentication -Authentication is the process of verifying that a user is who they claim to be and -should be handled by the framework you are using. Some already have a built-in -authentication system (like Django); others, you have to provide it manually. It's not -Strawberry's responsibility to authenticate the user, but it can be used to create a -mutation that handles the authentication's process. It's also very important not to -confuse authentication with authorization: authorization determines what an -authenticated user can do or which data they can access. In Strawberry, this is managed -with [`Permissions` classes](./permissions.md). +Authentication is the process of verifying that a user is who they claim to be +and should be handled by the framework you are using. Some already have a +built-in authentication system (like Django); others, you have to provide it +manually. It's not Strawberry's responsibility to authenticate the user, but it +can be used to create a mutation that handles the authentication's process. It's +also very important not to confuse authentication with authorization: +authorization determines what an authenticated user can do or which data they +can access. In Strawberry, this is managed with +[`Permissions` classes](./permissions.md). Let's see how to put together these concepts with an example. First, we define a `login` mutation where we authenticate credentials and return `LoginSucces` or -`LoginError` types depending on whether the user was successfully authenticated or not. +`LoginError` types depending on whether the user was successfully authenticated +or not. ```python import strawberry @@ -54,7 +56,8 @@ class Mutation: ### Access authenticated user in resolver -Its fairly common to require user information within a resolver. We can do that in a type safe way with a custom context dataclass. +Its fairly common to require user information within a resolver. We can do that +in a type safe way with a custom context dataclass. For example, in FastAPI this might look like this: diff --git a/docs/guides/errors.md b/docs/guides/errors.md index 6705109432..bd8fdb5fab 100644 --- a/docs/guides/errors.md +++ b/docs/guides/errors.md @@ -4,15 +4,21 @@ title: Dealing with errors # Dealing with errors -There are multiple different types of errors in GraphQL and each can be handled differently. +There are multiple different types of errors in GraphQL and each can be handled +differently. -In this guide we will outline the different types of errors that you will encounter when building a GraphQL server. +In this guide we will outline the different types of errors that you will +encounter when building a GraphQL server. -**Note**: By default Strawberry will log all execution errors to a `strawberry.execution` logger: [/docs/types/schema#handling-execution-errors](../types/schema#handling-execution-errors). +**Note**: By default Strawberry will log all execution errors to a +`strawberry.execution` logger: +[/docs/types/schema#handling-execution-errors](../types/schema#handling-execution-errors). ## GraphQL validation errors -GraphQL is strongly typed and so Strawberry validates all queries before executing them. If a query is invalid it isn’t executed and instead the response contains an `errors` list: +GraphQL is strongly typed and so Strawberry validates all queries before +executing them. If a query is invalid it isn’t executed and instead the response +contains an `errors` list: ```graphql+response { @@ -36,14 +42,18 @@ GraphQL is strongly typed and so Strawberry validates all queries before executi } ``` -Each error has a message, line, column and path to help you identify what part of the query caused the error. +Each error has a message, line, column and path to help you identify what part +of the query caused the error. -The validation rules are part of the GraphQL specification and built into Strawberry, so there’s not really a way to customize this behavior. -You can disable all validation by using the [DisableValidation](../extensions/disable-validation) extension. +The validation rules are part of the GraphQL specification and built into +Strawberry, so there’s not really a way to customize this behavior. You can +disable all validation by using the +[DisableValidation](../extensions/disable-validation) extension. ## GraphQL type errors -When a query is executed each field must resolve to the correct type. For example non-null fields cannot return None. +When a query is executed each field must resolve to the correct type. For +example non-null fields cannot return None. ```python import strawberry @@ -83,11 +93,14 @@ schema = strawberry.Schema(query=Query) } ``` -Each error has a message, line, column and path to help you identify what part of the query caused the error. +Each error has a message, line, column and path to help you identify what part +of the query caused the error. ## Unhandled execution errors -Sometimes a resolver will throw an unexpected error due to a programming error or an invalid assumption. When this happens Strawberry catches the error and exposes it in the top level `errors` field in the response. +Sometimes a resolver will throw an unexpected error due to a programming error +or an invalid assumption. When this happens Strawberry catches the error and +exposes it in the top level `errors` field in the response. ```python import strawberry @@ -136,9 +149,11 @@ schema = strawberry.Schema(query=Query) ## Expected errors -If an error is expected then it is often best to express it in the schema. This allows the client to deal with the error in a robust way. +If an error is expected then it is often best to express it in the schema. This +allows the client to deal with the error in a robust way. -This could be achieved by making the field optional when there is a possibility that the data won’t exist: +This could be achieved by making the field optional when there is a possibility +that the data won’t exist: ```python from typing import Optional @@ -156,9 +171,14 @@ class Query: return None ``` -When the expected error is more complicated it’s a good pattern to instead return a union of types that either represent an error or a success response. This pattern is often adopted with mutations where it’s important to be able to return more complicated error details to the client. +When the expected error is more complicated it’s a good pattern to instead +return a union of types that either represent an error or a success response. +This pattern is often adopted with mutations where it’s important to be able to +return more complicated error details to the client. -For example, say you have a `registerUser` mutation where you need to deal with the possibility that a user tries to register with a username that already exists. You might structure your mutation type like this: +For example, say you have a `registerUser` mutation where you need to deal with +the possibility that a user tries to register with a username that already +exists. You might structure your mutation type like this: ```python import strawberry @@ -196,7 +216,8 @@ def register_user(username: str, password: str) -> Response: return RegisterUserSuccess(user=user) ``` -Then your client can look at the `__typename` of the result to determine what to do next: +Then your client can look at the `__typename` of the result to determine what to +do next: ```graphql mutation RegisterUser($username: String!, $password: String!) { @@ -213,7 +234,9 @@ mutation RegisterUser($username: String!, $password: String!) { } ``` -This approach allows you to express the possible error states in the schema and so provide a robust interface for your client to account for all the potential outcomes from a mutation. +This approach allows you to express the possible error states in the schema and +so provide a robust interface for your client to account for all the potential +outcomes from a mutation. --- diff --git a/docs/guides/federation.md b/docs/guides/federation.md index 2c66e66acc..55fbffdf6d 100644 --- a/docs/guides/federation.md +++ b/docs/guides/federation.md @@ -198,8 +198,8 @@ able to find them. If you don't need any custom logic for your resolve_reference, you can omit it -and Strawberry will automatically instanciate the type for you. For example, -if we had a `Book` type with only an `id` field, Strawberry would be able to +and Strawberry will automatically instanciate the type for you. For example, if +we had a `Book` type with only an `id` field, Strawberry would be able to instanciate it for us based on the data returned by the gateway. ```python @@ -325,13 +325,18 @@ Strawberry and Federation. The repo is available here: ## Federated schema directives -Strawberry provides implementations for [Apollo federation-specific GraphQL directives](https://www.apollographql.com/docs/federation/federated-types/federated-directives/). +Strawberry provides implementations for +[Apollo federation-specific GraphQL directives](https://www.apollographql.com/docs/federation/federated-types/federated-directives/). -Some of these directives may not be necessary to directly include in your code, and are accessed through other means. +Some of these directives may not be necessary to directly include in your code, +and are accessed through other means. -- `@interfaceObject` (for more details, see [Extending interfaces](https://strawberry.rocks/docs/federation/entity-interfaces)) -- `@key` (for more details, see [Entities (Apollo Federation)](https://strawberry.rocks/docs/federation/entities)) -- `@link` (is automatically be added to the schema when any other federated schema directive is used) +- `@interfaceObject` (for more details, see + [Extending interfaces](https://strawberry.rocks/docs/federation/entity-interfaces)) +- `@key` (for more details, see + [Entities (Apollo Federation)](https://strawberry.rocks/docs/federation/entities)) +- `@link` (is automatically be added to the schema when any other federated + schema directive is used) Other directives you may need to specifically include when relevant. diff --git a/docs/guides/field-extensions.md b/docs/guides/field-extensions.md index cb79b79e18..f299733e94 100644 --- a/docs/guides/field-extensions.md +++ b/docs/guides/field-extensions.md @@ -4,14 +4,15 @@ title: Field extensions # Field extensions -Field extensions are a great way to implement reusable logic such as permissions or -pagination outside your resolvers. They wrap the underlying resolver and are able to -modify the field and all arguments passed to the resolver. +Field extensions are a great way to implement reusable logic such as permissions +or pagination outside your resolvers. They wrap the underlying resolver and are +able to modify the field and all arguments passed to the resolver. -The following examples only cover sync execution. To use extensions in async contexts, -please have a look at [Async Extensions and Resolvers](#async-extensions-and-resolvers) +The following examples only cover sync execution. To use extensions in async +contexts, please have a look at +[Async Extensions and Resolvers](#async-extensions-and-resolvers) @@ -34,10 +35,10 @@ class Query: ``` In this example, the `UpperCaseExtension` wraps the resolver of the `string` -field (`next`) and modifies the resulting string to be uppercase. -The extension will be called instead of the resolver and receives -the resolver function as the `next` argument. Therefore, it is important -to not modify any arguments that are passed to `next` in an incompatible way. +field (`next`) and modifies the resulting string to be uppercase. The extension +will be called instead of the resolver and receives the resolver function as the +`next` argument. Therefore, it is important to not modify any arguments that are +passed to `next` in an incompatible way. ```graphql+response query { @@ -53,14 +54,16 @@ query { -The `StrawberryField` API is not stable and might change in the future without warning. +The `StrawberryField` API is not stable and might change in the future without +warning. -In some cases, the extended field needs to be compatible with the added extension. -`FieldExtension` provides an `apply(field: StrawberryField)` method that can be -overriden to modify the field. It is called during _Schema Conversion_. -In the following example, we use `apply` to add a directive to the field: +In some cases, the extended field needs to be compatible with the added +extension. `FieldExtension` provides an `apply(field: StrawberryField)` method +that can be overriden to modify the field. It is called during _Schema +Conversion_. In the following example, we use `apply` to add a directive to the +field: ```python import time @@ -109,11 +112,11 @@ type Client { ## Combining multiple field extensions -When chaining multiple field extensions, the last extension in the list is called first. -Then, it calls the next extension until it reaches the resolver. -The return value of each extension is passed as an argument to the next extension. -This allows for creating a chain of field extensions that each perform a specific -transformation on the data being passed through them. +When chaining multiple field extensions, the last extension in the list is +called first. Then, it calls the next extension until it reaches the resolver. +The return value of each extension is passed as an argument to the next +extension. This allows for creating a chain of field extensions that each +perform a specific transformation on the data being passed through them. ```python @strawberry.field(extensions=[LowerCaseExtension(), UpperCaseExtension()]) @@ -123,35 +126,35 @@ def my_field(): -**Order matters**: the last extension in the list will be executed first, -while the first extension in the list extension will be applied to the field -first. This enables cases like adding relay pagination in front of an extension -that modifies the field's type. +**Order matters**: the last extension in the list will be executed first, while +the first extension in the list extension will be applied to the field first. +This enables cases like adding relay pagination in front of an extension that +modifies the field's type. ## Async Extensions and Resolvers -Field Extensions support async execution using the `resolve_async` method. -A field extension can either support `sync`, `async`, or both. The appropriate resolve -function will be automatically chosen based on the type of resolver and other -extensions. +Field Extensions support async execution using the `resolve_async` method. A +field extension can either support `sync`, `async`, or both. The appropriate +resolve function will be automatically chosen based on the type of resolver and +other extensions. -Since sync-only extensions cannot await the result of an async resolver, -they are not compatible with async resolvers or extensions. +Since sync-only extensions cannot await the result of an async resolver, they +are not compatible with async resolvers or extensions. The other way around is possible: you can add an async-only extension to a sync -resolver, or wrap sync-only extensions with it. -This is enabled by an automatic use of the `SyncToAsyncExtension`. Note that after -adding an async-only extension, you cannot wrap it with a sync-only extension anymore. +resolver, or wrap sync-only extensions with it. This is enabled by an automatic +use of the `SyncToAsyncExtension`. Note that after adding an async-only +extension, you cannot wrap it with a sync-only extension anymore. -To optimize the performance of your resolvers, it's recommended that you implement both -the `resolve` and `resolve_async` methods when using an extension on both sync and async -fields. -While the `SyncToAsyncExtension` is convenient, it may add unnecessary -overhead to your sync resolvers, leading to slightly decreased performance. +To optimize the performance of your resolvers, it's recommended that you +implement both the `resolve` and `resolve_async` methods when using an extension +on both sync and async fields. While the `SyncToAsyncExtension` is convenient, +it may add unnecessary overhead to your sync resolvers, leading to slightly +decreased performance. diff --git a/docs/guides/file-upload.md b/docs/guides/file-upload.md index abf0d7e9eb..f0b5da537c 100644 --- a/docs/guides/file-upload.md +++ b/docs/guides/file-upload.md @@ -8,8 +8,8 @@ All Strawberry integrations support multipart uploads as described in the [GraphQL multipart request specification](https://github.com/jaydenseric/graphql-multipart-request-spec). This includes support for uploading single files as well as lists of files. -Uploads can be used in mutations via the `Upload` scalar. -The type passed at runtime depends on the integration: +Uploads can be used in mutations via the `Upload` scalar. The type passed at +runtime depends on the integration: | Integration | Type | | ----------------------------------------- | ----------------------------------------------------------------------------------------------------------------------------------------------------- | @@ -25,12 +25,17 @@ The type passed at runtime depends on the integration: ## ASGI / FastAPI / Starlette -Since these integrations use asyncio for communication, the resolver _must_ be async. +Since these integrations use asyncio for communication, the resolver _must_ be +async. -Additionally, these servers rely on the `python-multipart` package, which is not included by Strawberry by default. It can be installed directly, or, for convenience, it is included in extras: `strawberry[asgi]` (for ASGI/Starlette) or `strawberry[fastapi]` (for FastAPI). For example: +Additionally, these servers rely on the `python-multipart` package, which is not +included by Strawberry by default. It can be installed directly, or, for +convenience, it is included in extras: `strawberry[asgi]` (for ASGI/Starlette) +or `strawberry[fastapi]` (for FastAPI). For example: - if using Pip, `pip install 'strawberry[fastapi]'` -- if using Poetry, `strawberry = { version = "...", extras = ["fastapi"] }` in `pyproject.toml`. +- if using Poetry, `strawberry = { version = "...", extras = ["fastapi"] }` in + `pyproject.toml`. Example: @@ -107,7 +112,8 @@ class Mutation: ## Sending file upload requests -The tricky part is sending the HTTP request from the client because it must follow the GraphQL multipart request specifications mentioned above. +The tricky part is sending the HTTP request from the client because it must +follow the GraphQL multipart request specifications mentioned above. The `multipart/form-data` POST request's data must include: @@ -115,7 +121,8 @@ The `multipart/form-data` POST request's data must include: - `map` key with mapping some multipart-data to exact GraphQL variable - and other keys for multipart-data which contains binary data of files -Assuming you have your schema up and running, here there are some requests examples: +Assuming you have your schema up and running, here there are some requests +examples: ### Sending one file diff --git a/docs/guides/pagination/connections.md b/docs/guides/pagination/connections.md index 1833d823d4..3996902645 100644 --- a/docs/guides/pagination/connections.md +++ b/docs/guides/pagination/connections.md @@ -4,11 +4,14 @@ title: Pagination - Implementing the Relay Connection Specification # Implementing the Relay Connection Specification -We naively implemented cursor based pagination in the [previous tutorial](./cursor-based.md). To ensure a consistent implementation -of this pattern, the Relay project has a formal [specification](https://relay.dev/graphql/connections.htm) you can follow for building -GraphQL APIs which use a cursor based connection pattern. +We naively implemented cursor based pagination in the +[previous tutorial](./cursor-based.md). To ensure a consistent implementation of +this pattern, the Relay project has a formal +[specification](https://relay.dev/graphql/connections.htm) you can follow for +building GraphQL APIs which use a cursor based connection pattern. -By the end of this tutorial, we should be able to return a connection of users when requested. +By the end of this tutorial, we should be able to return a connection of users +when requested. ```graphql+response query getUsers { @@ -67,8 +70,9 @@ query getUsers { ## Connections -A Connection represents a paginated relationship between two entities. This pattern is used when the relationship -itself has attributes. For example, we might have a connection of users to represent a paginated list of users. +A Connection represents a paginated relationship between two entities. This +pattern is used when the relationship itself has attributes. For example, we +might have a connection of users to represent a paginated list of users. Let us define a Connection type which takes in a Generic ObjectType. @@ -96,8 +100,8 @@ class Connection(Generic[GenericType]): Connections must have atleast two fields: `edges` and `page_info`. -The `page_info` field contains metadata about the connection. -Following the Relay specification, we can define a `PageInfo` type like this: +The `page_info` field contains metadata about the connection. Following the +Relay specification, we can define a `PageInfo` type like this: ```py line=22-38 # example.py @@ -147,8 +151,8 @@ You can read more about the `PageInfo` type at: The `edges` field must return a list type that wraps an edge type. -Following the Relay specification, let us define an Edge that takes -in a generic ObjectType. +Following the Relay specification, let us define an Edge that takes in a generic +ObjectType. ```py line=41-49 # example.py @@ -198,11 +202,12 @@ class Edge(Generic[GenericType]): cursor: str = strawberry.field(description="A cursor for use in pagination.") ``` -EdgeTypes must have atleast two fields - `cursor` and `node`. -Each edge has it's own cursor and item (represented by the `node` field). +EdgeTypes must have atleast two fields - `cursor` and `node`. Each edge has it's +own cursor and item (represented by the `node` field). -Now that we have the types needed to implement pagination using Relay Connections, let -us use them to paginate a list of users. For simplicity's sake, let our dataset be a list of dictionaries. +Now that we have the types needed to implement pagination using Relay +Connections, let us use them to paginate a list of users. For simplicity's sake, +let our dataset be a list of dictionaries. ```py line=7-32 # example.py @@ -279,19 +284,22 @@ class Edge(Generic[GenericType]): cursor: str = strawberry.field(description="A cursor for use in pagination.") ``` -Now is a good time to think of what we could use as a cursor for our dataset. Our cursor -needs to be an opaque value, which doesn't usually change over time. It makes sense to use -base64 encoded IDs of users as our cursor, as they fit both criteria. +Now is a good time to think of what we could use as a cursor for our dataset. +Our cursor needs to be an opaque value, which doesn't usually change over time. +It makes sense to use base64 encoded IDs of users as our cursor, as they fit +both criteria. -While working with Connections, it is a convention to base64-encode cursors. It provides a unified interface to the -end user. API clients need not bother about the type of data to paginate, and can pass unique IDs during pagination. -It also makes the cursors opaque. +While working with Connections, it is a convention to base64-encode cursors. It +provides a unified interface to the end user. API clients need not bother about +the type of data to paginate, and can pass unique IDs during pagination. It also +makes the cursors opaque. -Let us define a couple of helper functions to encode and decode cursors as follows: +Let us define a couple of helper functions to encode and decode cursors as +follows: ```py line=3,35-43 # example.py @@ -392,8 +400,8 @@ class Edge(Generic[GenericType]): cursor: str = strawberry.field(description="A cursor for use in pagination.") ``` -Let us define a `get_users` field which returns a connection of users, as well as an `UserType`. -Let us also plug our query into a schema. +Let us define a `get_users` field which returns a connection of users, as well +as an `UserType`. Let us also plug our query into a schema. ```python line=104-174 # example.py diff --git a/docs/guides/pagination/cursor-based.md b/docs/guides/pagination/cursor-based.md index f3358410a2..3620c050c0 100644 --- a/docs/guides/pagination/cursor-based.md +++ b/docs/guides/pagination/cursor-based.md @@ -6,8 +6,8 @@ title: Pagination - Cursor based Make sure to check our introduction to pagination [here](./overview.md)! -Let us implement cursor based pagination in GraphQL. By the end of this tutorial, we -should be able to return a paginated list of users when requested. +Let us implement cursor based pagination in GraphQL. By the end of this +tutorial, we should be able to return a paginated list of users when requested. ```graphql+response query getUsers { @@ -49,9 +49,9 @@ query getUsers { } ``` -The server needs to return a `cursor` along with the sliced user data, so that our client -can know what to query for next. The client could also provide a `limit` value, to specify -how much users it wants at a time. +The server needs to return a `cursor` along with the sliced user data, so that +our client can know what to query for next. The client could also provide a +`limit` value, to specify how much users it wants at a time. Let us model our schema like this: @@ -180,17 +180,21 @@ class Query: schema = strawberry.Schema(query=Query) ``` -Now is a good time to think of what we could use as a cursor for our dataset. Our cursor needs to be an opaque value, -which doesn't usually change over time. It makes sense to use base64 encoded IDs of users as our cursor, as they fit both criteria. +Now is a good time to think of what we could use as a cursor for our dataset. +Our cursor needs to be an opaque value, which doesn't usually change over time. +It makes sense to use base64 encoded IDs of users as our cursor, as they fit +both criteria. -It is good practice to base64-encode cursors, to provide a unified interface to the end user. API clients need not -bother about the type of data to paginate, and can pass unique IDs during pagination. It also makes the cursor opaque. +It is good practice to base64-encode cursors, to provide a unified interface to +the end user. API clients need not bother about the type of data to paginate, +and can pass unique IDs during pagination. It also makes the cursor opaque. -Let us define a couple of helper functions to encode and decode cursors as follows: +Let us define a couple of helper functions to encode and decode cursors as +follows: ```py line=3,35-43 # example.py @@ -291,9 +295,9 @@ class Query: schema = strawberry.Schema(query=Query) ``` -We're going to use the dataset we defined in our `get_users` field resolver. -Our field is going to accept two arguments, `limit` and `cursor`, to control pagination. -Let us implement the pagination logic as follows. +We're going to use the dataset we defined in our `get_users` field resolver. Our +field is going to accept two arguments, `limit` and `cursor`, to control +pagination. Let us implement the pagination logic as follows. Now, let us implement the pagination logic. @@ -427,8 +431,8 @@ schema = strawberry.Schema(query=Query) -Did you notice that cursor argument we defined is optional? That's because the client doesn't know -the cursor initially, when it makes the first request. +Did you notice that cursor argument we defined is optional? That's because the +client doesn't know the cursor initially, when it makes the first request. @@ -438,7 +442,8 @@ Now, let us start a debug server with our schema! strawberry server example:schema ``` -We should be able to query for users on the GraphiQL explorer. Here's a sample query for you! +We should be able to query for users on the GraphiQL explorer. Here's a sample +query for you! ```graphql query getUsers { diff --git a/docs/guides/pagination/offset-based.md b/docs/guides/pagination/offset-based.md index eae88ee684..55e54b2f0f 100644 --- a/docs/guides/pagination/offset-based.md +++ b/docs/guides/pagination/offset-based.md @@ -6,10 +6,12 @@ title: Pagination - Offset based Make sure to check our introduction to pagination [here](./overview.md)! -Let us implement offset-based pagination in GraphQL. By the end of this tutorial, we -should be able to return a sorted, filtered, and paginated list of users. +Let us implement offset-based pagination in GraphQL. By the end of this +tutorial, we should be able to return a sorted, filtered, and paginated list of +users. -Let us model the `User` type, which represents one user, with a name, occupation, and age. +Let us model the `User` type, which represents one user, with a name, +occupation, and age. ```python # example.py @@ -28,7 +30,8 @@ class User: return User(name=row["name"], occupation=row["occupation"], age=row["age"]) ``` -Let us now model the `PaginationWindow`, which represents one "slice" of sorted, filtered, and paginated items. +Let us now model the `PaginationWindow`, which represents one "slice" of sorted, +filtered, and paginated items. ```python Item = TypeVar("Item") @@ -45,11 +48,12 @@ class PaginationWindow(Generic[Item]): ) ``` -Note that `PaginationWindow` is generic - it can represent a slice of users, or a slice of any other type of -items that we might want to paginate. +Note that `PaginationWindow` is generic - it can represent a slice of users, or +a slice of any other type of items that we might want to paginate. -`PaginationWindow` also contains `total_items_count`, which specifies how many items there are in total in the filtered -dataset, so that the client knows what the highest offset value can be. +`PaginationWindow` also contains `total_items_count`, which specifies how many +items there are in total in the filtered dataset, so that the client knows what +the highest offset value can be. Let's define the query: @@ -86,9 +90,11 @@ class Query: schema = strawberry.Schema(query=Query) ``` -Now we'll define a mock dataset and implement the `get_pagination_window` function, which is used by the `users` query. +Now we'll define a mock dataset and implement the `get_pagination_window` +function, which is used by the `users` query. -For the sake of simplicity, our dataset will be an in-memory list containing four users: +For the sake of simplicity, our dataset will be an in-memory list containing +four users: ```python user_data = [ @@ -119,8 +125,8 @@ user_data = [ ] ``` -Here's the implementation of the `get_pagination_window` function. Note that it is generic and should work for all item types, -not only for the `User` type. +Here's the implementation of the `get_pagination_window` function. Note that it +is generic and should work for all item types, not only for the `User` type. ```python def get_pagination_window( @@ -169,21 +175,23 @@ def matches(item, filters): return True ``` -The above code first filters the dataset according to the given filters, then sorts the dataset according to the -given `order_by` field. +The above code first filters the dataset according to the given filters, then +sorts the dataset according to the given `order_by` field. -It then calculates `total_items_count` (this must be done after filtering), and then slices the relevant items -according to `offset` and `limit`. +It then calculates `total_items_count` (this must be done after filtering), and +then slices the relevant items according to `offset` and `limit`. -Finally, it converts the items to the given strawberry type, and returns a `PaginationWindow` containing these items, -as well as the `total_items_count`. +Finally, it converts the items to the given strawberry type, and returns a +`PaginationWindow` containing these items, as well as the `total_items_count`. -In a real project, you would probably replace this with code that fetches from a database using `offset` and `limit`. +In a real project, you would probably replace this with code that fetches from a +database using `offset` and `limit`. -If you're using Strawberry with the Django web framework, you might want to make use of the -Django pagination API. You can check it out [here](https://docs.djangoproject.com/en/4.0/topics/pagination/). +If you're using Strawberry with the Django web framework, you might want to make +use of the Django pagination API. You can check it out +[here](https://docs.djangoproject.com/en/4.0/topics/pagination/). @@ -201,9 +209,9 @@ You will get the following message: Running strawberry on http://0.0.0.0:8000/graphql 🍓 ``` -Go to [http://0.0.0.0:8000/graphql](http://0.0.0.0:8000/graphql) to -open **GraphiQL**, and run the following query to get first two users, -ordered by name: +Go to [http://0.0.0.0:8000/graphql](http://0.0.0.0:8000/graphql) to open +**GraphiQL**, and run the following query to get first two users, ordered by +name: ```graphql { @@ -245,8 +253,9 @@ The result should look like this: The result contains: - `items` - A list of the users in this pagination window -- `totalItemsCount` - The total number of items in the filtered dataset. In this case, since no filter was given - in the request, `totalItemsCount` is 4, which is equal to the total number of users in the in-memory dataset. +- `totalItemsCount` - The total number of items in the filtered dataset. In this + case, since no filter was given in the request, `totalItemsCount` is 4, which + is equal to the total number of users in the in-memory dataset. Get the next page of users by running the same query, after incrementing `offset` by `limit`. @@ -255,7 +264,8 @@ Repeat until `offset` reaches `totalItemsCount`. ## Running a Filtered Query -Let's run the query again, but this time we'll filter out some users based on their occupation. +Let's run the query again, but this time we'll filter out some users based on +their occupation. ```graphql { @@ -270,8 +280,8 @@ Let's run the query again, but this time we'll filter out some users based on th } ``` -By supplying `occupation: "ie"` in the query, we are requesting only users whose occupation -contains the substring "ie". +By supplying `occupation: "ie"` in the query, we are requesting only users whose +occupation contains the substring "ie". This is the result: diff --git a/docs/guides/pagination/overview.md b/docs/guides/pagination/overview.md index 2e4a00a389..8b309575f8 100644 --- a/docs/guides/pagination/overview.md +++ b/docs/guides/pagination/overview.md @@ -4,30 +4,36 @@ title: Pagination - Overview # Pagination -Whenever we deal with lists in GraphQL, we usually need to limit the number of items returned. Surely, we don't want to send massive lists of -items that take a considerable toll on the server! The goal of this guide is to help you get going fast with pagination! +Whenever we deal with lists in GraphQL, we usually need to limit the number of +items returned. Surely, we don't want to send massive lists of items that take a +considerable toll on the server! The goal of this guide is to help you get going +fast with pagination! ## Pagination at a Glance -Let us take a look at some of the common ways pagination can be implemented today! +Let us take a look at some of the common ways pagination can be implemented +today! ### Offset-Based Pagination -This type of pagination is widely used, and it is similar to the syntax we use when looking up database records. +This type of pagination is widely used, and it is similar to the syntax we use +when looking up database records. Here, the client specifies: - `limit`: The number of items to be obtained at a time, and - `offset`: The number of items to be skipped from the beginning. -Implementing offset-based pagination with an SQL database is straightforward. -We use the `limit` and `offset` values given to query for the items. +Implementing offset-based pagination with an SQL database is straightforward. We +use the `limit` and `offset` values given to query for the items. -Offset-based pagination also provides us the ability to skip ahead to any offset, -without first needing to get all the items before it. +Offset-based pagination also provides us the ability to skip ahead to any +offset, without first needing to get all the items before it. -Let us understand offset-based pagination better, with an example. Let us assume that we want to request a list of users, two at a time, from a server. -We start by sending a request to the server, with the desired `limit` and `offset` values. +Let us understand offset-based pagination better, with an example. Let us assume +that we want to request a list of users, two at a time, from a server. We start +by sending a request to the server, with the desired `limit` and `offset` +values. ```json { @@ -38,8 +44,9 @@ We start by sending a request to the server, with the desired `limit` and `offse -We are not sending GraphQL requests here, don't worry about the request format for now! We are looking into -pagination conceptually. We'll implement pagination in GraphQL later! +We are not sending GraphQL requests here, don't worry about the request format +for now! We are looking into pagination conceptually. We'll implement pagination +in GraphQL later! @@ -64,7 +71,8 @@ The response from the server would be: } ``` -To get the next two users, we can send another request, incrementing `offset` by the value of `limit`. +To get the next two users, we can send another request, incrementing `offset` by +the value of `limit`. ```json { @@ -73,14 +81,17 @@ To get the next two users, we can send another request, incrementing `offset` by } ``` -We can repeat this process, incrementing `offset` by the value of `limit`, until we get an empty result. +We can repeat this process, incrementing `offset` by the value of `limit`, until +we get an empty result. #### Pagination Metadata -In the example above, the result contained no metadata, only the items at the requested offset and limit. +In the example above, the result contained no metadata, only the items at the +requested offset and limit. -It may be useful to add metadata to the result. For example, the metadata may specify how many items there -are in total, so that the client knows what the greatest offset value can be. +It may be useful to add metadata to the result. For example, the metadata may +specify how many items there are in total, so that the client knows what the +greatest offset value can be. ```json { @@ -95,45 +106,54 @@ are in total, so that the client knows what the greatest offset value can be. #### Using page_number Instead of offset -Instead of using `limit` and `offset` as the pagination parameters, it may be more useful to use `page_number` -and `page_size`. +Instead of using `limit` and `offset` as the pagination parameters, it may be +more useful to use `page_number` and `page_size`. -In such a case, the metadata in the result can be `pages_count`. The client starts the pagination at `page_number` 1, -incrementing by 1 each time to get the next page, and ending when `page_size` is reached. +In such a case, the metadata in the result can be `pages_count`. The client +starts the pagination at `page_number` 1, incrementing by 1 each time to get the +next page, and ending when `page_size` is reached. -This approach may be more in line with what a typical client actually needs when paginating. +This approach may be more in line with what a typical client actually needs when +paginating. #### Limitations of Offset-Based Pagination Offset-based pagination has a few limitations: -- It is not suitable for large datasets, because we need to access offset + limit number of items from the dataset, before discarding the offset - and only returning the requested items. -- It doesn't work well in environments where records are frequently added or removed, because in such cases, the page window becomes - inconsistent and unreliable. This may result in duplicate items or skipped items across pages. +- It is not suitable for large datasets, because we need to access offset + + limit number of items from the dataset, before discarding the offset and only + returning the requested items. +- It doesn't work well in environments where records are frequently added or + removed, because in such cases, the page window becomes inconsistent and + unreliable. This may result in duplicate items or skipped items across pages. -However, it provides a quick way to get started, and works well with small-medium datasets. When your dataset scales, you will -need a reliable and consistent way to handle pagination. +However, it provides a quick way to get started, and works well with +small-medium datasets. When your dataset scales, you will need a reliable and +consistent way to handle pagination. ### Cursor based pagination Strawberry provides a cursor based pagination implementing the -[relay spec](https://relay.dev/docs/guides/graphql-server-specification/). -You can read more about it in the [relay](../relay) page. +[relay spec](https://relay.dev/docs/guides/graphql-server-specification/). You +can read more about it in the [relay](../relay) page. -Cursor based pagination, also known as keyset pagination, works by returning a pointer to a specific item in the dataset. On subsequent requests, -the server returns results after the given pointer. This method addresses the drawbacks of using offset pagination, but does so by making certain trade offs: +Cursor based pagination, also known as keyset pagination, works by returning a +pointer to a specific item in the dataset. On subsequent requests, the server +returns results after the given pointer. This method addresses the drawbacks of +using offset pagination, but does so by making certain trade offs: -- The cursor must be based on a unique, sequential identifier in the given source. +- The cursor must be based on a unique, sequential identifier in the given + source. - There is no concept of the total number of pages or results in the dataset. - The client can’t jump to a specific page. -Let us understand cursor based pagination better, with the example given below. We want to request a list of users, 2 at a time, from -the server. We don't know the cursor initially, so we will assign it a null value. +Let us understand cursor based pagination better, with the example given below. +We want to request a list of users, 2 at a time, from the server. We don't know +the cursor initially, so we will assign it a null value. ```json { @@ -164,7 +184,8 @@ The response from the server would be: } ``` -The next cursor returned by the server can be used to get the next set of users from the server. +The next cursor returned by the server can be used to get the next set of users +from the server. ```json { @@ -173,7 +194,8 @@ The next cursor returned by the server can be used to get the next set of users } ``` -This is an example of forward pagination, but pagination can be done backwards too! +This is an example of forward pagination, but pagination can be done backwards +too! ## Implementing pagination in GraphQL diff --git a/docs/guides/permissions.md b/docs/guides/permissions.md index 25b23d34af..908931f30b 100644 --- a/docs/guides/permissions.md +++ b/docs/guides/permissions.md @@ -29,14 +29,16 @@ class Query: user: str = strawberry.field(permission_classes=[IsAuthenticated]) ``` -Your `has_permission` method should check if this request has permission to access the -field. Note that the `has_permission` method can also be asynchronous. +Your `has_permission` method should check if this request has permission to +access the field. Note that the `has_permission` method can also be +asynchronous. -If the `has_permission` method returns a truthy value then the field access will go -ahead. Otherwise, an error will be raised using the `message` class attribute. +If the `has_permission` method returns a truthy value then the field access will +go ahead. Otherwise, an error will be raised using the `message` class +attribute. -Take a look at our [Dealing with Errors Guide](/docs/guides/errors) for more information -on how errors are handled. +Take a look at our [Dealing with Errors Guide](/docs/guides/errors) for more +information on how errors are handled. ```json { @@ -54,11 +56,13 @@ on how errors are handled. Accessing the current user information to implement your permission checks depends on the web framework you are using. -Most frameworks will have a `Request` object where you can either access the current -user directly or access headers/cookies/query parameters to authenticate the user. +Most frameworks will have a `Request` object where you can either access the +current user directly or access headers/cookies/query parameters to authenticate +the user. -All the Strawberry integrations provide this Request object in the `info.context` object -that is accessible in every resolver and in the `has_permission` function. +All the Strawberry integrations provide this Request object in the +`info.context` object that is accessible in every resolver and in the +`has_permission` function. You can find more details about a specific framework integration under the "Integrations" heading in the navigation. @@ -109,11 +113,12 @@ _[Issue #830](https://github.com/strawberry-graphql/strawberry/issues/830)._ ## Custom Error Extensions & classes -In addition to the message, permissions automatically add pre-defined error extensions to the error, and -can use a custom `GraphQLError` class. This can be configured by modifying -the `error_class` and `error_extensions` attributes on the `BasePermission` class. -Error extensions will be propagated to the response as specified in -the [GraphQL spec](https://strawberry.rocks/docs/types/exceptions). +In addition to the message, permissions automatically add pre-defined error +extensions to the error, and can use a custom `GraphQLError` class. This can be +configured by modifying the `error_class` and `error_extensions` attributes on +the `BasePermission` class. Error extensions will be propagated to the response +as specified in the +[GraphQL spec](https://strawberry.rocks/docs/types/exceptions). ```python import typing @@ -135,7 +140,8 @@ class IsAuthenticated(BasePermission): # Advanced Permissions -Internally, permissions in strawberry use the `PermissionsExtension` field extension. +Internally, permissions in strawberry use the `PermissionsExtension` field +extension. The following snippet @@ -166,10 +172,10 @@ Using the new `PermissionExtension` API, permissions support even more features: ## Silent errors -In some cases, it is practical to avoid throwing an error when the user has no permission to access -the field and instead return `None` or an empty list to the client. -To return `None` or `[]` instead of raising an error, the `fail_silently ` keyword -argument on `PermissionExtension` can be set to `True`: +In some cases, it is practical to avoid throwing an error when the user has no +permission to access the field and instead return `None` or an empty list to the +client. To return `None` or `[]` instead of raising an error, the +`fail_silently ` keyword argument on `PermissionExtension` can be set to `True`: Note that this will only work if the field returns a type that @@ -192,21 +198,23 @@ class Query: return "ABC" ``` -Please note than in many cases, defensive programming is a better approach than using `fail_silently`. -Clients will no longer be able to distinguish between a permission error and an empty result. -Before implementing `fail_silently`, consider if it is possible to use alternative solutions like -the `@skip` or `@include` directives to dynamically exclude fields from the query for users without permission. -Check the GraphQL documentation for more information on [directives](https://graphql.org/learn/queries/#directives). +Please note than in many cases, defensive programming is a better approach than +using `fail_silently`. Clients will no longer be able to distinguish between a +permission error and an empty result. Before implementing `fail_silently`, +consider if it is possible to use alternative solutions like the `@skip` or +`@include` directives to dynamically exclude fields from the query for users +without permission. Check the GraphQL documentation for more information on +[directives](https://graphql.org/learn/queries/#directives). ## Customizable Error Handling -To customize the error handling, the `on_unauthorized` method on -the `BasePermission` class can be used. Further changes can be implemented by +To customize the error handling, the `on_unauthorized` method on the +`BasePermission` class can be used. Further changes can be implemented by subclassing the `PermissionExtension` class. ## Schema Directives Permissions will automatically be added as schema directives to the schema. This -behavior can be altered by setting the `add_directives` to `False` -on `PermissionExtension`, or by setting the `_schema_directive` class attribute of the -permission class to a custom directive. +behavior can be altered by setting the `add_directives` to `False` on +`PermissionExtension`, or by setting the `_schema_directive` class attribute of +the permission class to a custom directive. diff --git a/docs/guides/relay.md b/docs/guides/relay.md index 24dbf8f1f8..016dee3377 100644 --- a/docs/guides/relay.md +++ b/docs/guides/relay.md @@ -7,8 +7,8 @@ title: Relay ## What is Relay? The relay spec defines some interfaces that GraphQL servers can follow to allow -clients to interact with them in a more efficient way. The spec makes two -core assumptions about a GraphQL server: +clients to interact with them in a more efficient way. The spec makes two core +assumptions about a GraphQL server: 1. It provides a mechanism for refetching an object 2. It provides a description of how to page through connections. @@ -29,8 +29,9 @@ class Fruit: We want it to have a globally unique ID, a way to retrieve a paginated results list of it and a way to refetch if if necessary. For that, we need to inherit it -from the `Node` interface, annotate its attribute that will be used for `GlobalID` -generation with `relay.NodeID` and implement its `resolve_nodes` abstract method. +from the `Node` interface, annotate its attribute that will be used for +`GlobalID` generation with `relay.NodeID` and implement its `resolve_nodes` +abstract method. ```python import strawberry @@ -65,9 +66,9 @@ all_fruits: Dict[int, Fruit] Explaining what we did here: - We annotated `code` using `relay.NodeID[int]`. This makes `code` a - [Private](../types/private.md) type, which will not be exposed to the - GraphQL API, and also tells the `Node` interface that it should use - its value to generate its `id: GlobalID!` for the `Fruit` type. + [Private](../types/private.md) type, which will not be exposed to the GraphQL + API, and also tells the `Node` interface that it should use its value to + generate its `id: GlobalID!` for the `Fruit` type. - We also implemented the `resolve_nodes` abstract method. This method is responsible for retrieving the `Fruit` instances given its `id`. Because @@ -76,8 +77,8 @@ Explaining what we did here: The `GlobalID` gets generated by getting the base64 encoded version of the -string `:`. In the example above, the `Fruit` with a code -of `1` would have its `GlobalID` as `base64("Fruit:1")` = `RnJ1aXQ6MQ==` +string `:`. In the example above, the `Fruit` with a code of +`1` would have its `GlobalID` as `base64("Fruit:1")` = `RnJ1aXQ6MQ==` @@ -220,14 +221,15 @@ for most use cases. that you can override what the slice does by customizing the `__getitem__` method of the object returned by your nodes resolver. -For example, when working with `Django`, `resolve_nodes` can return a `QuerySet`, -meaning that the slice on it will translate to a `LIMIT`/`OFFSET` in the SQL -query, which will fetch only the data that is needed from the database. +For example, when working with `Django`, `resolve_nodes` can return a +`QuerySet`, meaning that the slice on it will translate to a `LIMIT`/`OFFSET` in +the SQL query, which will fetch only the data that is needed from the database. Also note that if that object doesn't have a `__getitem__` attribute, it will use `itertools.islice` to paginate it, meaning that when a generator is being -resolved it will only generate as much results as needed for the given pagination, -the worst case scenario being the last results needing to be returned. +resolved it will only generate as much results as needed for the given +pagination, the worst case scenario being the last results needing to be +returned. @@ -307,17 +309,17 @@ with more than one type. ### Custom connection arguments -By default the connection will automatically insert some arguments for it -to be able to paginate the results. Those are: +By default the connection will automatically insert some arguments for it to be +able to paginate the results. Those are: - `before`: Returns the items in the list that come before the specified cursor - `after`: Returns the items in the list that come after the " "specified cursor - `first`: Returns the first n items from the list - `last`: Returns the items in the list that come after the " "specified cursor -You can still define extra arguments to be used by your own resolver or -custom pagination logic. For example, suppose we want to return the pagination -of all fruits whose name starts with a given string. We could do that like this: +You can still define extra arguments to be used by your own resolver or custom +pagination logic. For example, suppose we want to return the pagination of all +fruits whose name starts with a given string. We could do that like this: ```python @strawberry.type @@ -349,13 +351,13 @@ type Query { ### Convert the node to its proper type when resolving the connection -The connection expects that the resolver will return a list of objects that is -a subclass of its `NodeType`. But there may be situations where you are resolving +The connection expects that the resolver will return a list of objects that is a +subclass of its `NodeType`. But there may be situations where you are resolving something that needs to be converted to the proper type, like an ORM model. -In this case you can subclass the `relay.Connection`/`relay.ListConnection` -and provide a custom `resolve_node` method to it, which by default returns -the node as is. For example: +In this case you can subclass the `relay.Connection`/`relay.ListConnection` and +provide a custom `resolve_node` method to it, which by default returns the node +as is. For example: ```python import strawberry @@ -395,17 +397,17 @@ class Query: The main advantage of this approach instead of converting it inside the custom resolver is that the `Connection` will paginate the `QuerySet` first, which in -case of django will make sure that only the paginated results are fetched from the -database. After that, the `resolve_node` function will be called for each result -to retrieve the correct object for it. +case of django will make sure that only the paginated results are fetched from +the database. After that, the `resolve_node` function will be called for each +result to retrieve the correct object for it. -We used django for this example, but the same applies to any other other -similar use case, like SQLAlchemy, etc. +We used django for this example, but the same applies to any other other similar +use case, like SQLAlchemy, etc. ### The GlobalID scalar -The `GlobalID` scalar is a special object that contains all the info necessary to -identify and retrieve a given object that implements the `Node` interface. +The `GlobalID` scalar is a special object that contains all the info necessary +to identify and retrieve a given object that implements the `Node` interface. It can for example be useful in a mutation, to receive and object and retrieve it in its resolver. For example: @@ -438,5 +440,6 @@ class Mutation: return fruit ``` -In the example above, you can also access the type name directly with `id.type_name`, -the raw node ID with `id.id`, or even resolve the type itself with `id.resolve_type(info)`. +In the example above, you can also access the type name directly with +`id.type_name`, the raw node ID with `id.id`, or even resolve the type itself +with `id.resolve_type(info)`. diff --git a/docs/guides/schema-export.md b/docs/guides/schema-export.md index 74e3fc6fe3..96e04f34eb 100644 --- a/docs/guides/schema-export.md +++ b/docs/guides/schema-export.md @@ -4,11 +4,11 @@ title: Schema export # Schema export -Sometimes IDE plugins and code generation tools require you to provide a GraphQL schema -definition. +Sometimes IDE plugins and code generation tools require you to provide a GraphQL +schema definition. -Strawberry provides a command to export your schema definition. -The exported schema will be described in the GraphQL schema definition language (SDL). +Strawberry provides a command to export your schema definition. The exported +schema will be described in the GraphQL schema definition language (SDL). You can export your schema using the following command: @@ -20,7 +20,8 @@ where `schema` is the name of a Strawberry schema symbol and `package.module` is the qualified name of the module containing the symbol. The symbol name defaults to `schema` if not specified. -In order to store the exported schema in a file, pipes or redirection can be utilized: +In order to store the exported schema in a file, pipes or redirection can be +utilized: ```bash strawberry export-schema package.module:schema > schema.graphql diff --git a/docs/integrations/aiohttp.md b/docs/integrations/aiohttp.md index 90e89dc7c6..ebae48abab 100644 --- a/docs/integrations/aiohttp.md +++ b/docs/integrations/aiohttp.md @@ -32,7 +32,9 @@ app.router.add_route("*", "/graphql", GraphQLView(schema=schema)) The `GraphQLView` accepts two options at the moment: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests diff --git a/docs/integrations/asgi.md b/docs/integrations/asgi.md index 92156433ba..2f6543c422 100644 --- a/docs/integrations/asgi.md +++ b/docs/integrations/asgi.md @@ -32,7 +32,9 @@ app with `uvicorn server:app` The `GraphQL` app accepts two options at the moment: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests diff --git a/docs/integrations/chalice.md b/docs/integrations/chalice.md index 00ad384d3c..dbfd68f8af 100644 --- a/docs/integrations/chalice.md +++ b/docs/integrations/chalice.md @@ -4,8 +4,8 @@ title: Chalice # Chalice -Strawberry comes with an AWS Chalice integration. It provides a view that you can -use to serve your GraphQL schema: +Strawberry comes with an AWS Chalice integration. It provides a view that you +can use to serve your GraphQL schema: Use the Chalice CLI to create a new project @@ -57,14 +57,16 @@ And then run `chalice local` to start the localhost chalice local ``` -The GraphiQL interface can then be opened in your browser on http://localhost:8000/graphql +The GraphiQL interface can then be opened in your browser on +http://localhost:8000/graphql ## Options The `GraphQLView` accepts two options at the moment: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphiql`: optional, defaults to `True`, whether to enable the GraphiQL interface. +- `graphiql`: optional, defaults to `True`, whether to enable the GraphiQL + interface. ## Extending the view diff --git a/docs/integrations/channels.md b/docs/integrations/channels.md index 205998fb90..775fdd00c3 100644 --- a/docs/integrations/channels.md +++ b/docs/integrations/channels.md @@ -155,25 +155,24 @@ class Subscription: ) ``` -Explanation: `Info.context["ws"]` or `Info.context["request"]` is a pointer to the -[`ChannelsConsumer`](#channelsconsumer) instance. Here we have first sent a +Explanation: `Info.context["ws"]` or `Info.context["request"]` is a pointer to +the [`ChannelsConsumer`](#channelsconsumer) instance. Here we have first sent a message to all the channel_layer groups (specified in the subscription argument `rooms`) that we have joined the chat. -The `ChannelsConsumer` instance is shared between all subscriptions created in -a single websocket connection. The `ws.listen_to_channel` context manager will return -a function to yield all -messages sent using the given message `type` (`chat.message` in the above example) -but does not ensure that the message was sent to the same group or groups that -it was called with - if another subscription using the same `ChannelsConsumer` -also uses `ws.listen_to_channel` with some other group names, those will be returned -as well. +The `ChannelsConsumer` instance is shared between all subscriptions created in a +single websocket connection. The `ws.listen_to_channel` context manager will +return a function to yield all messages sent using the given message `type` +(`chat.message` in the above example) but does not ensure that the message was +sent to the same group or groups that it was called with - if another +subscription using the same `ChannelsConsumer` also uses `ws.listen_to_channel` +with some other group names, those will be returned as well. -In the example we ensure `message["room_id"] in room_ids` before passing messages -on to the subscription client to ensure subscriptions only receive messages for -the chat rooms requested in that subscription. +In the example we ensure `message["room_id"] in room_ids` before passing +messages on to the subscription client to ensure subscriptions only receive +messages for the chat rooms requested in that subscription. @@ -409,9 +408,9 @@ after entering the `listen_to_channel` context manger. ## Testing -We provide a minimal application communicator (`GraphQLWebsocketCommunicator`) for subscribing. -Here is an example based on the tutorial above: _Make sure you have pytest-async -installed_ +We provide a minimal application communicator (`GraphQLWebsocketCommunicator`) +for subscribing. Here is an example based on the tutorial above: _Make sure you +have pytest-async installed_ ```python from channels.testing import WebsocketCommunicator @@ -495,9 +494,9 @@ def test_send_message_via_channels_chat_joinChatRooms_recieves(self): --- -The HTTP and WebSockets protocol are handled by different base classes. HTTP uses -`GraphQLHTTPConsumer` and WebSockets uses `GraphQLWSConsumer`. Both of them can -be extended: +The HTTP and WebSockets protocol are handled by different base classes. HTTP +uses `GraphQLHTTPConsumer` and WebSockets uses `GraphQLWSConsumer`. Both of them +can be extended: ## GraphQLHTTPConsumer (HTTP) @@ -506,7 +505,9 @@ be extended: `GraphQLHTTPConsumer` supports the same options as all other integrations: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `subscriptions_enabled`: optional boolean paramenter enabling subscriptions in @@ -522,7 +523,8 @@ We allow to extend `GraphQLHTTPConsumer`, by overriding the following methods: ### Context -The default context returned by `get_context()` is a `dict` that includes the following keys by default: +The default context returned by `get_context()` is a `dict` that includes the +following keys by default: - `request`: A `ChannelsRequest` object with the following fields and methods: - `consumer`: The `GraphQLHTTPConsumer` instance for this connection @@ -530,8 +532,10 @@ The default context returned by `get_context()` is a `dict` that includes the fo - `headers`: A dict containing the headers of the request - `method`: The HTTP method of the request - `content_type`: The content type of the request -- `response` A `TemporalResponse` object, that can be used to influence the HTTP response: - - `status_code`: The status code of the response, if there are no execution errors (defaults to `200`) +- `response` A `TemporalResponse` object, that can be used to influence the HTTP + response: + - `status_code`: The status code of the response, if there are no execution + errors (defaults to `200`) - `headers`: Any additional headers that should be send with the response ## GraphQLWSConsumer (WebSockets / Subscriptions) @@ -554,18 +558,22 @@ We allow to extend `GraphQLWSConsumer`, by overriding the following methods: ### Context -The default context returned by `get_context()` is a `dict` and it includes the following keys by default: +The default context returned by `get_context()` is a `dict` and it includes the +following keys by default: -- `request`: The `GraphQLWSConsumer` instance of the current connection. It can be used to access the connection - scope, e.g. `info.context["ws"].headers` allows access to any headers. +- `request`: The `GraphQLWSConsumer` instance of the current connection. It can + be used to access the connection scope, e.g. `info.context["ws"].headers` + allows access to any headers. - `ws`: The same as `request` -- `connection_params`: Any `connection_params`, see [Authenticating Subscriptions](/docs/general/subscriptions#authenticating-subscriptions) +- `connection_params`: Any `connection_params`, see + [Authenticating Subscriptions](/docs/general/subscriptions#authenticating-subscriptions) ## Example for defining a custom context -Here is an example for extending the base classes to offer a different context object in your resolvers. -For the HTTP integration, you can also have properties to access the current user and the -session. Both properties depend on the `AuthMiddlewareStack` wrapper. +Here is an example for extending the base classes to offer a different context +object in your resolvers. For the HTTP integration, you can also have properties +to access the current user and the session. Both properties depend on the +`AuthMiddlewareStack` wrapper. ```python from django.contrib.auth.models import AnonymousUser @@ -630,8 +638,8 @@ class GraphQLWSConsumer(BaseGraphQLWSConsumer): ) ``` -You can import and use the extended `GraphQLHTTPConsumer` and `GraphQLWSConsumer` classes in your -`myproject.asgi.py` file as shown before. +You can import and use the extended `GraphQLHTTPConsumer` and +`GraphQLWSConsumer` classes in your `myproject.asgi.py` file as shown before. --- @@ -664,9 +672,11 @@ everything else to the Django application. ### ChannelsConsumer -Strawberries extended [`AsyncConsumer`](https://channels.readthedocs.io/en/stable/topics/consumers.html#consumers). +Strawberries extended +[`AsyncConsumer`](https://channels.readthedocs.io/en/stable/topics/consumers.html#consumers). -Every graphql session will have an instance of this class inside `info.context["ws"]` (WebSockets) or `info.context["request"].consumer` (HTTP). +Every graphql session will have an instance of this class inside +`info.context["ws"]` (WebSockets) or `info.context["request"].consumer` (HTTP). #### properties diff --git a/docs/integrations/creating-an-integration.md b/docs/integrations/creating-an-integration.md index a2be35c3a9..87f143259e 100644 --- a/docs/integrations/creating-an-integration.md +++ b/docs/integrations/creating-an-integration.md @@ -65,8 +65,8 @@ The methods above are the bare minimum that you need to implement to create a view. They are all required, but you can also override other methods to change the behaviour of the view. -On top of that we also need a request adapter, here's the base class for the async -version: +On top of that we also need a request adapter, here's the base class for the +async version: ```python from strawberry.http.types import HTTPMethod, QueryParams, FormData diff --git a/docs/integrations/django.md b/docs/integrations/django.md index e4f19ec5c1..d557bc1e4d 100644 --- a/docs/integrations/django.md +++ b/docs/integrations/django.md @@ -20,8 +20,10 @@ urlpatterns = [ ] ``` -Strawberry only provides a GraphQL view for Django, [Strawberry GraphQL Django](https://github.com/strawberry-graphql/strawberry-graphql-django) provides integration with the models. -`import strawberry_django` should do the same as `import strawberry.django` if both libraries are installed. +Strawberry only provides a GraphQL view for Django, +[Strawberry GraphQL Django](https://github.com/strawberry-graphql/strawberry-graphql-django) +provides integration with the models. `import strawberry_django` should do the +same as `import strawberry.django` if both libraries are installed. You'd also need to add `strawberry_django` to the `INSTALLED_APPS` of your project, this is needed to provide the template for the GraphiQL interface. @@ -31,7 +33,9 @@ project, this is needed to provide the template for the GraphiQL interface. The `GraphQLView` accepts the following arguments: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `subscriptions_enabled`: optional boolean paramenter enabling subscriptions in @@ -168,7 +172,9 @@ project, this is needed to provide the template for the GraphiQL interface. The `AsyncGraphQLView` accepts the following arguments: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `subscriptions_enabled`: optional boolean paramenter enabling subscriptions in diff --git a/docs/integrations/fastapi.md b/docs/integrations/fastapi.md index 4231d83e55..0def346e8a 100644 --- a/docs/integrations/fastapi.md +++ b/docs/integrations/fastapi.md @@ -45,7 +45,9 @@ app.include_router(graphql_app, prefix="/graphql") The `GraphQLRouter` accepts the following options: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `context_getter`: optional FastAPI dependency for providing custom context diff --git a/docs/integrations/litestar.md b/docs/integrations/litestar.md index 59cf921582..31a99ac554 100644 --- a/docs/integrations/litestar.md +++ b/docs/integrations/litestar.md @@ -4,10 +4,9 @@ title: Litestar # Litestar -Strawberry comes with an integration for -[Litestar](https://litestar.dev/) by providing a -`make_graphql_controller` function that can be used to create a GraphQL -controller. +Strawberry comes with an integration for [Litestar](https://litestar.dev/) by +providing a `make_graphql_controller` function that can be used to create a +GraphQL controller. See the example below for integrating Litestar with Strawberry: @@ -41,7 +40,9 @@ The `make_graphql_controller` function accepts the following options: - `schema`: mandatory, the schema created by `strawberry.Schema`. - `path`: optional, defaults to ``, the path where the GraphQL endpoint will be mounted. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `context_getter`: optional Litestar dependency for providing custom context @@ -53,13 +54,18 @@ The `make_graphql_controller` function accepts the following options: for websockets. - `keep_alive_interval`: optional, defaults to `1`, the interval in seconds for keep alive messages. -- `subscription_protocols` optional, defaults to `(GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL)`, the allowed subscription protocols -- `connection_init_wait_timeout` optional, default to `timedelta(minutes=1)`, the maximum time to wait for the connection initialization message when using `graphql-transport-ws` [protocol](<[https://](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit)>) +- `subscription_protocols` optional, defaults to + `(GRAPHQL_TRANSPORT_WS_PROTOCOL, GRAPHQL_WS_PROTOCOL)`, the allowed + subscription protocols +- `connection_init_wait_timeout` optional, default to `timedelta(minutes=1)`, + the maximum time to wait for the connection initialization message when using + `graphql-transport-ws` + [protocol](<[https://](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit)>) ## context_getter -The `context_getter` option allows you to provide a Litestar dependency that return a custom context object that -can be used in your resolver. +The `context_getter` option allows you to provide a Litestar dependency that +return a custom context object that can be used in your resolver. ```python import strawberry @@ -90,7 +96,8 @@ GraphQLController = make_graphql_controller( app = Litestar(route_handlers=[GraphQLController]) ``` -The `context_getter` is a standard Litestar dependency and can receive any existing dependency: +The `context_getter` is a standard Litestar dependency and can receive any +existing dependency: ```python import strawberry @@ -129,7 +136,9 @@ GraphQLController = make_graphql_controller( app = Litestar(route_handlers=[GraphQLController]) ``` -You can also use a class-based custom context. To do this, you must inherit from `BaseContext` [msgspec Struct](https://jcristharif.com/msgspec/structs.html) or an `InvalidCustomContext` exception will be raised. +You can also use a class-based custom context. To do this, you must inherit from +`BaseContext` [msgspec Struct](https://jcristharif.com/msgspec/structs.html) or +an `InvalidCustomContext` exception will be raised. ```python import strawberry @@ -177,17 +186,24 @@ app = Litestar(route_handlers=[GraphQLController]) ### Context typing -In our previous example using class based context, the actual runtime context a `CustomContext` type. Because it inherits from `BaseContext`, the `request`, `socket` and `response` attributes are typed as optional. +In our previous example using class based context, the actual runtime context a +`CustomContext` type. Because it inherits from `BaseContext`, the `request`, +`socket` and `response` attributes are typed as optional. -When inside a query/mutation resolver, `request` and `response` are always set and `socket` is only set in subscriptions. +When inside a query/mutation resolver, `request` and `response` are always set +and `socket` is only set in subscriptions. -To distinguish theses cases typing wise, the integration provides two classes that will help you to enforce strong typing: +To distinguish theses cases typing wise, the integration provides two classes +that will help you to enforce strong typing: ```python from strawberry.litestar import HTTPContextType, WebSocketContextType ``` -These classes does not actually exists at runtime, they are intended to be used to define a custom `Info` type with proper context typing. Taking over our previous example with class based custom context, here it how we can define two `Info` types for both queries/mutations and subscriptions: +These classes does not actually exists at runtime, they are intended to be used +to define a custom `Info` type with proper context typing. Taking over our +previous example with class based custom context, here it how we can define two +`Info` types for both queries/mutations and subscriptions: ```python import strawberry diff --git a/docs/integrations/pydantic.md b/docs/integrations/pydantic.md index b2e7e67ee1..e9cabb0aaf 100644 --- a/docs/integrations/pydantic.md +++ b/docs/integrations/pydantic.md @@ -42,15 +42,15 @@ class UserType: ``` The `strawberry.experimental.pydantic.type` decorator accepts a Pydantic model -and wraps a class that contains dataclass style fields with `strawberry.auto` as the type -annotation. The fields marked with `strawberry.auto` will inherit their types from the -Pydantic model. +and wraps a class that contains dataclass style fields with `strawberry.auto` as +the type annotation. The fields marked with `strawberry.auto` will inherit their +types from the Pydantic model. If you want to include all of the fields from your Pydantic model, you can instead pass `all_fields=True` to the decorator. --> **Note** Care should be taken to avoid accidentally exposing fields that --> weren't meant to be exposed on an API using this feature. +-> **Note** Care should be taken to avoid accidentally exposing fields that -> +weren't meant to be exposed on an API using this feature. ```python import strawberry @@ -279,9 +279,10 @@ instance = input_data.to_pydantic() ### Constrained types -Strawberry supports [pydantic constrained types](https://pydantic-docs.helpmanual.io/usage/types/#constrained-types). -Note that constraint is not enforced in the graphql type. Thus, we recommend always working on the pydantic -type such that the validation is enforced. +Strawberry supports +[pydantic constrained types](https://pydantic-docs.helpmanual.io/usage/types/#constrained-types). +Note that constraint is not enforced in the graphql type. Thus, we recommend +always working on the pydantic type such that the validation is enforced. ```python+schema from pydantic import BaseModel, conlist @@ -318,9 +319,10 @@ type Query { ### Classes with `__get_validators__` -Pydantic BaseModels may define a custom type with [`__get_validators__`](https://pydantic-docs.helpmanual.io/usage/types/#classes-with-__get_validators__) -logic. You will need to add a scalar type and add the mapping to the `scalar_overrides` -argument in the Schema class. +Pydantic BaseModels may define a custom type with +[`__get_validators__`](https://pydantic-docs.helpmanual.io/usage/types/#classes-with-__get_validators__) +logic. You will need to add a scalar type and add the mapping to the +`scalar_overrides` argument in the Schema class. ```python import strawberry diff --git a/docs/integrations/sanic.md b/docs/integrations/sanic.md index f9e43f604f..690969e0a0 100644 --- a/docs/integrations/sanic.md +++ b/docs/integrations/sanic.md @@ -25,7 +25,9 @@ app.add_route( The `GraphQLView` accepts two options at the moment: - `schema`: mandatory, the schema created by `strawberry.Schema`. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `def encode_json(self, data: GraphQLHTTPResponse) -> str` diff --git a/docs/integrations/starlette.md b/docs/integrations/starlette.md index 7d98b7a2f0..a830af4a42 100644 --- a/docs/integrations/starlette.md +++ b/docs/integrations/starlette.md @@ -4,7 +4,8 @@ title: Starlette # Starlette -Strawberry provides support for [Starlette](https://www.starlette.io/) with the ASGI integration. +Strawberry provides support for [Starlette](https://www.starlette.io/) with the +ASGI integration. See below example for integrating Starlette with Strawberry: @@ -21,4 +22,5 @@ app.add_route("/graphql", graphql_app) app.add_websocket_route("/graphql", graphql_app) ``` -For more information about Strawberry ASGI refer to [the documentation on ASGI](./asgi.md) +For more information about Strawberry ASGI refer to +[the documentation on ASGI](./asgi.md) diff --git a/docs/integrations/starlite.md b/docs/integrations/starlite.md index e2cfec7da0..9b09b71f6e 100644 --- a/docs/integrations/starlite.md +++ b/docs/integrations/starlite.md @@ -44,7 +44,9 @@ The `make_graphql_controller` function accepts the following options: - `schema`: mandatory, the schema created by `strawberry.Schema`. - `path`: optional, defaults to ``, the path where the GraphQL endpoint will be mounted. -- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or to disable it by passing `None`. +- `graphql_ide`: optional, defaults to `"graphiql"`, allows to choose the + GraphQL IDE interface (one of `graphiql`, `apollo-sandbox` or `pathfinder`) or + to disable it by passing `None`. - `allow_queries_via_get`: optional, defaults to `True`, whether to enable queries via `GET` requests - `context_getter`: optional Starlite dependency for providing custom context diff --git a/docs/operations/deployment.md b/docs/operations/deployment.md index 65c6a05401..dcdfd09502 100644 --- a/docs/operations/deployment.md +++ b/docs/operations/deployment.md @@ -4,13 +4,15 @@ title: Deployment # Deployment -Before deploying your GraphQL app to production you should disable `GraphiQL` and `Introspection`. +Before deploying your GraphQL app to production you should disable `GraphiQL` +and `Introspection`. ## Why are they a problem? 1. They can reveal sensitive information (e.g. internal business logic) -2. They make it easier for malicious parties to reverse engineer your GraphQL API +2. They make it easier for malicious parties to reverse engineer your GraphQL + API [See more on this topic](https://www.apollographql.com/blog/graphql/security/why-you-should-disable-graphql-introspection-in-production/) @@ -18,11 +20,13 @@ Before deploying your GraphQL app to production you should disable `GraphiQL` an ### GraphiQL -GraphiQL is useful during testing and development but should be disabled in production by default. +GraphiQL is useful during testing and development but should be disabled in +production by default. It can be turned off by setting the `graphql_ide` option to `None` -See the Strawberry Options documentation for the integration you are using for more information on how to disable it: +See the Strawberry Options documentation for the integration you are using for +more information on how to disable it: - [AIOHTTP](../integrations/aiohttp.md#options) - [ASGI](../integrations/asgi.md#options) @@ -36,13 +40,16 @@ See the Strawberry Options documentation for the integration you are using for m ### Introspection -Introspection should primarily be used as a discovery and diagnostic tool for testing and development, and should be disabled in production by default. +Introspection should primarily be used as a discovery and diagnostic tool for +testing and development, and should be disabled in production by default. -You can disable introspection by [adding a validation rule extension](../extensions/add-validation-rules.md#more-examples). +You can disable introspection by +[adding a validation rule extension](../extensions/add-validation-rules.md#more-examples). ## Security extensions -Strawberry provides some security extensions to limit various aspects of the GraphQL document. These are recommended in production. +Strawberry provides some security extensions to limit various aspects of the +GraphQL document. These are recommended in production. - [query depth](../extensions/query-depth-limiter.md) - [max number of aliases](../extensions/max-aliases-limiter.md) @@ -50,7 +57,8 @@ Strawberry provides some security extensions to limit various aspects of the Gra # More resources -See the documentation for the integration you are using for more information on deployment: +See the documentation for the integration you are using for more information on +deployment: - [AIOHTTP](https://docs.aiohttp.org/en/stable/deployment.html) - [Django](https://docs.djangoproject.com/en/4.0/howto/deployment/) @@ -59,4 +67,7 @@ See the documentation for the integration you are using for more information on - [Sanic](https://sanic.dev/en/guide/deployment/configuration.html) - [Chalice](https://aws.github.io/chalice/quickstart.html#deploying) -The docs for [ASGI](https://asgi.readthedocs.io/en/latest/index.html) and [Starlette](https://www.starlette.io/) do not provide an official deployment guide, but you may find the documentation for other frameworks that use ASGI servers useful (e.g. [FastAPI](https://fastapi.tiangolo.com/deployment/)) +The docs for [ASGI](https://asgi.readthedocs.io/en/latest/index.html) and +[Starlette](https://www.starlette.io/) do not provide an official deployment +guide, but you may find the documentation for other frameworks that use ASGI +servers useful (e.g. [FastAPI](https://fastapi.tiangolo.com/deployment/)) diff --git a/docs/operations/testing.md b/docs/operations/testing.md index 0e53ff7f5c..a3aca51741 100644 --- a/docs/operations/testing.md +++ b/docs/operations/testing.md @@ -5,14 +5,15 @@ title: Testing # Testing The GraphiQL playground integrated with Strawberry available at -[http://localhost:8000/graphql](http://localhost:8000/graphql) (if you run the schema -with `strawberry server`) can be a good place to start testing your queries and -mutations. However, at some point, while you are developing your application (or even -before if you are practising TDD), you may want to create some automated tests. +[http://localhost:8000/graphql](http://localhost:8000/graphql) (if you run the +schema with `strawberry server`) can be a good place to start testing your +queries and mutations. However, at some point, while you are developing your +application (or even before if you are practising TDD), you may want to create +some automated tests. We can use the Strawberry `schema` object we defined in the -[Getting Started tutorial](../index.md#step-5-create-our-schema-and-run-it) to run our -first test: +[Getting Started tutorial](../index.md#step-5-create-our-schema-and-run-it) to +run our first test: ```python def test_query(): @@ -41,17 +42,18 @@ def test_query(): This `test_query` example: -1. defines the query we will test against; it accepts one argument, `title`, as input +1. defines the query we will test against; it accepts one argument, `title`, as + input 2. executes the query and assigns the result to a `result` variable -3. asserts that the result is what we are expecting: nothing in `errors` and our desired - book in `data` +3. asserts that the result is what we are expecting: nothing in `errors` and our + desired book in `data` -As you may have noticed, we explicitly defined the query variable `title`, and we passed -it separately with the `variable_values` argument, but we could have directly hardcoded -the `title` in the query string instead. We did this on purpose because usually the -query's arguments will be dynamic and, as we want to test our application as close to -production as possible, it wouldn't make much sense to hardcode the variables in the -query. +As you may have noticed, we explicitly defined the query variable `title`, and +we passed it separately with the `variable_values` argument, but we could have +directly hardcoded the `title` in the query string instead. We did this on +purpose because usually the query's arguments will be dynamic and, as we want to +test our application as close to production as possible, it wouldn't make much +sense to hardcode the variables in the query. ## Testing Async @@ -144,5 +146,5 @@ async def test_subscription(): index += 1 ``` -As you can see testing Subscriptions is a bit more complicated because we want to check -the result of each individual result. +As you can see testing Subscriptions is a bit more complicated because we want +to check the result of each individual result. diff --git a/docs/operations/tracing.md b/docs/operations/tracing.md index 12a9ebf87e..aca6efb2db 100644 --- a/docs/operations/tracing.md +++ b/docs/operations/tracing.md @@ -110,7 +110,8 @@ services: healthcheck: interval: 10s retries: 12 - test: curl -s http://localhost:9200/_cluster/health | grep -vq + test: + curl -s http://localhost:9200/_cluster/health | grep -vq '"status":"red"' kibana: diff --git a/docs/types/exceptions.md b/docs/types/exceptions.md index 5c86b90a77..e9104caea7 100644 --- a/docs/types/exceptions.md +++ b/docs/types/exceptions.md @@ -45,13 +45,13 @@ class Query: ### MissingTypesForGenericError -This exception is raised when a `Generic` type is added to the Strawberry Schema without -passing any type to make it concrete. +This exception is raised when a `Generic` type is added to the Strawberry Schema +without passing any type to make it concrete. ### MultipleStrawberryArgumentsError -This exception is raised when `strawberry.argument` is used multiple times in a type -annotation. +This exception is raised when `strawberry.argument` is used multiple times in a +type annotation. ```python import strawberry diff --git a/docs/types/object-types.md b/docs/types/object-types.md index eb9c3e7fa5..2000c74b72 100644 --- a/docs/types/object-types.md +++ b/docs/types/object-types.md @@ -4,7 +4,10 @@ title: Object types # Object types -Object types are the fundamentals of any GraphQL schema, they are used to define the kind of objects that exist in a schema. Object types are created by defining a name and a list of fields, here’s an example object type defined using the GraphQL schema language: +Object types are the fundamentals of any GraphQL schema, they are used to define +the kind of objects that exist in a schema. Object types are created by defining +a name and a list of fields, here’s an example object type defined using the +GraphQL schema language: ```graphql type Character { @@ -15,18 +18,22 @@ type Character { ## A note on Query, Mutation and Subscription -While reading about GraphQL you might have encountered 3 special object types: `Query`, `Mutation` and `Subscription`. They are defined as standard object types, with the difference that they are also used as entry points for your schema (also referred as root types). +While reading about GraphQL you might have encountered 3 special object types: +`Query`, `Mutation` and `Subscription`. They are defined as standard object +types, with the difference that they are also used as entry points for your +schema (also referred as root types). - `Query` is the entry point for all the query operations - `Mutation` is the entry point for all the mutations - `Subscription` is the entry point for all the subscriptions. -For a walk-through on how to define schemas, read the [schema -basics](/docs/general/schema-basics.md). +For a walk-through on how to define schemas, read the +[schema basics](/docs/general/schema-basics.md). ## Defining object types -In Strawberry, you can define object types by using the `@strawberry.type` decorator, like this: +In Strawberry, you can define object types by using the `@strawberry.type` +decorator, like this: ```python+schema import strawberry @@ -78,6 +85,8 @@ type Book { Creates an object type from a class definition. -`name`: if set this will be the GraphQL name, otherwise the GraphQL will be generated by camel-casing the name of the class. +`name`: if set this will be the GraphQL name, otherwise the GraphQL will be +generated by camel-casing the name of the class. -`description`: this is the GraphQL description that will be returned when introspecting the schema or when navigating the schema using GraphiQL. +`description`: this is the GraphQL description that will be returned when +introspecting the schema or when navigating the schema using GraphiQL. diff --git a/docs/types/private.md b/docs/types/private.md index c22f22b9e1..43fe67aa33 100644 --- a/docs/types/private.md +++ b/docs/types/private.md @@ -4,9 +4,8 @@ title: Private Fields # Private Fields -Private (external) fields can provide local context for later resolution. -These fields will act as plain fields so will not be exposed in the GraphQL -API. +Private (external) fields can provide local context for later resolution. These +fields will act as plain fields so will not be exposed in the GraphQL API. Some uses include: @@ -15,8 +14,8 @@ Some uses include: # Defining a private field -Specifying a field with `strawberry.Private[...]` will desigate it as -internal and not for GraphQL. +Specifying a field with `strawberry.Private[...]` will desigate it as internal +and not for GraphQL. # Example @@ -41,9 +40,9 @@ class Stringable: return template.format(my=self.value) ``` -The `Private[...]` type lets Strawberry know that this field is not -a GraphQL field. "value" is a regular field on the class, but it is not -exposed on the GraphQL API. +The `Private[...]` type lets Strawberry know that this field is not a GraphQL +field. "value" is a regular field on the class, but it is not exposed on the +GraphQL API. ```python @strawberry.type diff --git a/docs/types/resolvers.md b/docs/types/resolvers.md index e08a7cb735..1040cd18b7 100644 --- a/docs/types/resolvers.md +++ b/docs/types/resolvers.md @@ -225,9 +225,9 @@ class User: For either decorated resolvers or Python functions, there is a third option which is to annotate one of the parameters with the type `Parent`. This is particularly useful if the parent resolver returns a type other than the -strawberry type that the resolver is defined within, as it allows you to -specify the type of the parent object. This comes up particularly often -for resolvers that return ORMs: +strawberry type that the resolver is defined within, as it allows you to specify +the type of the parent object. This comes up particularly often for resolvers +that return ORMs: ```python import dataclass diff --git a/docs/types/scalars.md b/docs/types/scalars.md index 13abde9461..9ce3e49e7e 100644 --- a/docs/types/scalars.md +++ b/docs/types/scalars.md @@ -4,9 +4,9 @@ title: Scalars # Scalars -Scalar types represent concrete values at the leaves of a query. For example -in the following query the name field will resolve to a scalar type -(in this case it's a `String` type): +Scalar types represent concrete values at the leaves of a query. For example in +the following query the name field will resolve to a scalar type (in this case +it's a `String` type): ```graphql+response { @@ -29,14 +29,21 @@ There are several built-in scalars, and you can define custom scalars too. - `String`, maps to Python’s `str` - `Int`, a signed 32-bit integer, maps to Python’s `int` -- `Float`, a signed double-precision floating-point value, maps to Python’s `float` +- `Float`, a signed double-precision floating-point value, maps to Python’s + `float` - `Boolean`, true or false, maps to Python’s `bool` - `ID`, a specialised `String` for representing unique object identifiers -- `Date`, an ISO-8601 encoded [date](https://docs.python.org/3/library/datetime.html#date-objects) -- `DateTime`, an ISO-8601 encoded [datetime](https://docs.python.org/3/library/datetime.html#datetime-objects) -- `Time`, an ISO-8601 encoded [time](https://docs.python.org/3/library/datetime.html#time-objects) -- `Decimal`, a [Decimal](https://docs.python.org/3/library/decimal.html#decimal.Decimal) value serialized as a string -- `UUID`, a [UUID](https://docs.python.org/3/library/uuid.html#uuid.UUID) value serialized as a string +- `Date`, an ISO-8601 encoded + [date](https://docs.python.org/3/library/datetime.html#date-objects) +- `DateTime`, an ISO-8601 encoded + [datetime](https://docs.python.org/3/library/datetime.html#datetime-objects) +- `Time`, an ISO-8601 encoded + [time](https://docs.python.org/3/library/datetime.html#time-objects) +- `Decimal`, a + [Decimal](https://docs.python.org/3/library/decimal.html#decimal.Decimal) + value serialized as a string +- `UUID`, a [UUID](https://docs.python.org/3/library/uuid.html#uuid.UUID) value + serialized as a string - `Void`, always null, maps to Python’s `None` Fields can return built-in scalars by using the Python equivalent: @@ -126,7 +133,8 @@ assert results.data == {"base64": "aGk="} -The `Base16`, `Base32` and `Base64` scalar types are available in `strawberry.scalars` +The `Base16`, `Base32` and `Base64` scalar types are available in +`strawberry.scalars` ```python from strawberry.scalars import Base16, Base32, Base64 @@ -228,7 +236,8 @@ To override with a pendulum instance you'd want to serialize and parse_value like the above example. Let's throw them in a class this time. In addition we'll be using the `Union` clause to combine possible input types. -Since pendulum isn't typed yet, we'll have to silence mypy's errors using `# type: ignore` +Since pendulum isn't typed yet, we'll have to silence mypy's errors using +`# type: ignore` ```python import pendulum @@ -264,10 +273,11 @@ date_time = strawberry.scalar( ## BigInt (64-bit integers) -Python by default allows, integer size to be 2^64. However the graphql spec has capped it to 2^32. +Python by default allows, integer size to be 2^64. However the graphql spec has +capped it to 2^32. -This will inevitably raise errors. Instead of using strings on the client as a workaround, -you could use the following scalar: +This will inevitably raise errors. Instead of using strings on the client as a +workaround, you could use the following scalar: ```python # This is needed because GraphQL does not support 64 bit integers @@ -279,7 +289,8 @@ BigInt = strawberry.scalar( ) ``` -You can adapt your schema to automatically use this scalar for all integers by using the `scalar_overrides` parameter +You can adapt your schema to automatically use this scalar for all integers by +using the `scalar_overrides` parameter Only use this override if you expect most of your integers to be 64-bit. Since most GraphQL schemas diff --git a/docs/types/schema-configurations.md b/docs/types/schema-configurations.md index 2e8832bda8..8a6811dc7f 100644 --- a/docs/types/schema-configurations.md +++ b/docs/types/schema-configurations.md @@ -4,11 +4,12 @@ title: Schema Configurations # Schema Configurations -Strawberry allows to customise how the schema is generated by passing configurations. -At the moment we only allow to disable auto camel casing of fields and arguments names. +Strawberry allows to customise how the schema is generated by passing +configurations. At the moment we only allow to disable auto camel casing of +fields and arguments names. -To customise the schema you can create an instance of `StrawberryConfig`, as shown in the -example below: +To customise the schema you can create an instance of `StrawberryConfig`, as +shown in the example below: ```python import strawberry @@ -24,8 +25,8 @@ class Query: schema = strawberry.Schema(query=Query, config=StrawberryConfig(auto_camel_case=False)) ``` -In this case we are disabling the auto camel casing feature, so your output schema -will look like this: +In this case we are disabling the auto camel casing feature, so your output +schema will look like this: ```graphql type Query { diff --git a/docs/types/union.md b/docs/types/union.md index 91caa082b3..e6734da0e5 100644 --- a/docs/types/union.md +++ b/docs/types/union.md @@ -4,10 +4,10 @@ title: Union types # Union types -Union types are similar to [interfaces](/docs/types/interfaces) however, while interfaces -dictate fields that must be common to all implementations, unions do not. Unions -only represent a selection of allowed types and make no requirements on those -types. Here’s a union, expressed in +Union types are similar to [interfaces](/docs/types/interfaces) however, while +interfaces dictate fields that must be common to all implementations, unions do +not. Unions only represent a selection of allowed types and make no requirements +on those types. Here’s a union, expressed in [GraphQL Schema Definition Language](https://graphql.org/learn/schema/#type-language) (SDL): @@ -37,16 +37,17 @@ searchMedia(term: "strawberry") { ``` Here, the `searchMedia` field returns `[MediaItem!]!`, a list where each member -is part of the `MediaItem` union. So, for each member, we want to select different -fields depending on which kind of object that member is. We can do that by using +is part of the `MediaItem` union. So, for each member, we want to select +different fields depending on which kind of object that member is. We can do +that by using [inline fragments](https://graphql.org/learn/queries/#inline-fragments). ## Defining unions In Strawberry there are two ways to define a union: -You can use the `Union` type from the `typing` module which will -autogenerate the type name from the names of the union members: +You can use the `Union` type from the `typing` module which will autogenerate +the type name from the names of the union members: ```python+schema from typing import Union @@ -87,8 +88,8 @@ type Image { } ``` -Or if you need to specify a name or a description for a union you can use Annotated -with the `strawberry.union` function: +Or if you need to specify a name or a description for a union you can use +Annotated with the `strawberry.union` function: ```python+schema import strawberry @@ -145,9 +146,9 @@ Sometimes you might want to define a union with only one member. This is useful for future proofing your schema, for example if you want to add more types to the union in the future. -Python's `typing.Union` does not really support this use case, but using Annotated -and `strawberry.union` you can tell Strawberry that you want to define a union -with only one member: +Python's `typing.Union` does not really support this use case, but using +Annotated and `strawberry.union` you can tell Strawberry that you want to define +a union with only one member: ```python+schema import strawberry diff --git a/poetry.lock b/poetry.lock index 8f96f31f1a..ce48bec520 100644 --- a/poetry.lock +++ b/poetry.lock @@ -13,87 +13,87 @@ files = [ [[package]] name = "aiohttp" -version = "3.9.1" +version = "3.9.3" description = "Async http client/server framework (asyncio)" optional = false python-versions = ">=3.8" files = [ - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:e1f80197f8b0b846a8d5cf7b7ec6084493950d0882cc5537fb7b96a69e3c8590"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:c72444d17777865734aa1a4d167794c34b63e5883abb90356a0364a28904e6c0"}, - {file = "aiohttp-3.9.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:9b05d5cbe9dafcdc733262c3a99ccf63d2f7ce02543620d2bd8db4d4f7a22f83"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c4fa235d534b3547184831c624c0b7c1e262cd1de847d95085ec94c16fddcd5"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:289ba9ae8e88d0ba16062ecf02dd730b34186ea3b1e7489046fc338bdc3361c4"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:bff7e2811814fa2271be95ab6e84c9436d027a0e59665de60edf44e529a42c1f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:81b77f868814346662c96ab36b875d7814ebf82340d3284a31681085c051320f"}, - {file = "aiohttp-3.9.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3b9c7426923bb7bd66d409da46c41e3fb40f5caf679da624439b9eba92043fa6"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:8d44e7bf06b0c0a70a20f9100af9fcfd7f6d9d3913e37754c12d424179b4e48f"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:22698f01ff5653fe66d16ffb7658f582a0ac084d7da1323e39fd9eab326a1f26"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ca7ca5abfbfe8d39e653870fbe8d7710be7a857f8a8386fc9de1aae2e02ce7e4"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:8d7f98fde213f74561be1d6d3fa353656197f75d4edfbb3d94c9eb9b0fc47f5d"}, - {file = "aiohttp-3.9.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:5216b6082c624b55cfe79af5d538e499cd5f5b976820eac31951fb4325974501"}, - {file = "aiohttp-3.9.1-cp310-cp310-win32.whl", hash = "sha256:0e7ba7ff228c0d9a2cd66194e90f2bca6e0abca810b786901a569c0de082f489"}, - {file = "aiohttp-3.9.1-cp310-cp310-win_amd64.whl", hash = "sha256:c7e939f1ae428a86e4abbb9a7c4732bf4706048818dfd979e5e2839ce0159f23"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:df9cf74b9bc03d586fc53ba470828d7b77ce51b0582d1d0b5b2fb673c0baa32d"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:ecca113f19d5e74048c001934045a2b9368d77b0b17691d905af18bd1c21275e"}, - {file = "aiohttp-3.9.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:8cef8710fb849d97c533f259103f09bac167a008d7131d7b2b0e3a33269185c0"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:bea94403a21eb94c93386d559bce297381609153e418a3ffc7d6bf772f59cc35"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:91c742ca59045dce7ba76cab6e223e41d2c70d79e82c284a96411f8645e2afff"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:6c93b7c2e52061f0925c3382d5cb8980e40f91c989563d3d32ca280069fd6a87"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ee2527134f95e106cc1653e9ac78846f3a2ec1004cf20ef4e02038035a74544d"}, - {file = "aiohttp-3.9.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:11ff168d752cb41e8492817e10fb4f85828f6a0142b9726a30c27c35a1835f01"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:b8c3a67eb87394386847d188996920f33b01b32155f0a94f36ca0e0c635bf3e3"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:c7b5d5d64e2a14e35a9240b33b89389e0035e6de8dbb7ffa50d10d8b65c57449"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:69985d50a2b6f709412d944ffb2e97d0be154ea90600b7a921f95a87d6f108a2"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:c9110c06eaaac7e1f5562caf481f18ccf8f6fdf4c3323feab28a93d34cc646bd"}, - {file = "aiohttp-3.9.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d737e69d193dac7296365a6dcb73bbbf53bb760ab25a3727716bbd42022e8d7a"}, - {file = "aiohttp-3.9.1-cp311-cp311-win32.whl", hash = "sha256:4ee8caa925aebc1e64e98432d78ea8de67b2272252b0a931d2ac3bd876ad5544"}, - {file = "aiohttp-3.9.1-cp311-cp311-win_amd64.whl", hash = "sha256:a34086c5cc285be878622e0a6ab897a986a6e8bf5b67ecb377015f06ed316587"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f800164276eec54e0af5c99feb9494c295118fc10a11b997bbb1348ba1a52065"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:500f1c59906cd142d452074f3811614be04819a38ae2b3239a48b82649c08821"}, - {file = "aiohttp-3.9.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:0b0a6a36ed7e164c6df1e18ee47afbd1990ce47cb428739d6c99aaabfaf1b3af"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:69da0f3ed3496808e8cbc5123a866c41c12c15baaaead96d256477edf168eb57"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:176df045597e674fa950bf5ae536be85699e04cea68fa3a616cf75e413737eb5"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b796b44111f0cab6bbf66214186e44734b5baab949cb5fb56154142a92989aeb"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f27fdaadce22f2ef950fc10dcdf8048407c3b42b73779e48a4e76b3c35bca26c"}, - {file = "aiohttp-3.9.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:bcb6532b9814ea7c5a6a3299747c49de30e84472fa72821b07f5a9818bce0f66"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:54631fb69a6e44b2ba522f7c22a6fb2667a02fd97d636048478db2fd8c4e98fe"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:4b4c452d0190c5a820d3f5c0f3cd8a28ace48c54053e24da9d6041bf81113183"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:cae4c0c2ca800c793cae07ef3d40794625471040a87e1ba392039639ad61ab5b"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:565760d6812b8d78d416c3c7cfdf5362fbe0d0d25b82fed75d0d29e18d7fc30f"}, - {file = "aiohttp-3.9.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:54311eb54f3a0c45efb9ed0d0a8f43d1bc6060d773f6973efd90037a51cd0a3f"}, - {file = "aiohttp-3.9.1-cp312-cp312-win32.whl", hash = "sha256:85c3e3c9cb1d480e0b9a64c658cd66b3cfb8e721636ab8b0e746e2d79a7a9eed"}, - {file = "aiohttp-3.9.1-cp312-cp312-win_amd64.whl", hash = "sha256:11cb254e397a82efb1805d12561e80124928e04e9c4483587ce7390b3866d213"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:8a22a34bc594d9d24621091d1b91511001a7eea91d6652ea495ce06e27381f70"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:598db66eaf2e04aa0c8900a63b0101fdc5e6b8a7ddd805c56d86efb54eb66672"}, - {file = "aiohttp-3.9.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:2c9376e2b09895c8ca8b95362283365eb5c03bdc8428ade80a864160605715f1"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:41473de252e1797c2d2293804e389a6d6986ef37cbb4a25208de537ae32141dd"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9c5857612c9813796960c00767645cb5da815af16dafb32d70c72a8390bbf690"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:ffcd828e37dc219a72c9012ec44ad2e7e3066bec6ff3aaa19e7d435dbf4032ca"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:219a16763dc0294842188ac8a12262b5671817042b35d45e44fd0a697d8c8361"}, - {file = "aiohttp-3.9.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f694dc8a6a3112059258a725a4ebe9acac5fe62f11c77ac4dcf896edfa78ca28"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:bcc0ea8d5b74a41b621ad4a13d96c36079c81628ccc0b30cfb1603e3dfa3a014"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:90ec72d231169b4b8d6085be13023ece8fa9b1bb495e4398d847e25218e0f431"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:cf2a0ac0615842b849f40c4d7f304986a242f1e68286dbf3bd7a835e4f83acfd"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:0e49b08eafa4f5707ecfb321ab9592717a319e37938e301d462f79b4e860c32a"}, - {file = "aiohttp-3.9.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:2c59e0076ea31c08553e868cec02d22191c086f00b44610f8ab7363a11a5d9d8"}, - {file = "aiohttp-3.9.1-cp38-cp38-win32.whl", hash = "sha256:4831df72b053b1eed31eb00a2e1aff6896fb4485301d4ccb208cac264b648db4"}, - {file = "aiohttp-3.9.1-cp38-cp38-win_amd64.whl", hash = "sha256:3135713c5562731ee18f58d3ad1bf41e1d8883eb68b363f2ffde5b2ea4b84cc7"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:cfeadf42840c1e870dc2042a232a8748e75a36b52d78968cda6736de55582766"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:70907533db712f7aa791effb38efa96f044ce3d4e850e2d7691abd759f4f0ae0"}, - {file = "aiohttp-3.9.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:cdefe289681507187e375a5064c7599f52c40343a8701761c802c1853a504558"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d7481f581251bb5558ba9f635db70908819caa221fc79ee52a7f58392778c636"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:49f0c1b3c2842556e5de35f122fc0f0b721334ceb6e78c3719693364d4af8499"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:0d406b01a9f5a7e232d1b0d161b40c05275ffbcbd772dc18c1d5a570961a1ca4"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8d8e4450e7fe24d86e86b23cc209e0023177b6d59502e33807b732d2deb6975f"}, - {file = "aiohttp-3.9.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3c0266cd6f005e99f3f51e583012de2778e65af6b73860038b968a0a8888487a"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:ab221850108a4a063c5b8a70f00dd7a1975e5a1713f87f4ab26a46e5feac5a0e"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:c88a15f272a0ad3d7773cf3a37cc7b7d077cbfc8e331675cf1346e849d97a4e5"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:237533179d9747080bcaad4d02083ce295c0d2eab3e9e8ce103411a4312991a0"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:02ab6006ec3c3463b528374c4cdce86434e7b89ad355e7bf29e2f16b46c7dd6f"}, - {file = "aiohttp-3.9.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:04fa38875e53eb7e354ece1607b1d2fdee2d175ea4e4d745f6ec9f751fe20c7c"}, - {file = "aiohttp-3.9.1-cp39-cp39-win32.whl", hash = "sha256:82eefaf1a996060602f3cc1112d93ba8b201dbf5d8fd9611227de2003dddb3b7"}, - {file = "aiohttp-3.9.1-cp39-cp39-win_amd64.whl", hash = "sha256:9b05d33ff8e6b269e30a7957bd3244ffbce2a7a35a81b81c382629b80af1a8bf"}, - {file = "aiohttp-3.9.1.tar.gz", hash = "sha256:8fc49a87ac269d4529da45871e2ffb6874e87779c3d0e2ccd813c0899221239d"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:939677b61f9d72a4fa2a042a5eee2a99a24001a67c13da113b2e30396567db54"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:1f5cd333fcf7590a18334c90f8c9147c837a6ec8a178e88d90a9b96ea03194cc"}, + {file = "aiohttp-3.9.3-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:82e6aa28dd46374f72093eda8bcd142f7771ee1eb9d1e223ff0fa7177a96b4a5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f56455b0c2c7cc3b0c584815264461d07b177f903a04481dfc33e08a89f0c26b"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:bca77a198bb6e69795ef2f09a5f4c12758487f83f33d63acde5f0d4919815768"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e083c285857b78ee21a96ba1eb1b5339733c3563f72980728ca2b08b53826ca5"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:ab40e6251c3873d86ea9b30a1ac6d7478c09277b32e14745d0d3c6e76e3c7e29"}, + {file = "aiohttp-3.9.3-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:df822ee7feaaeffb99c1a9e5e608800bd8eda6e5f18f5cfb0dc7eeb2eaa6bbec"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:acef0899fea7492145d2bbaaaec7b345c87753168589cc7faf0afec9afe9b747"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:cd73265a9e5ea618014802ab01babf1940cecb90c9762d8b9e7d2cc1e1969ec6"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:a78ed8a53a1221393d9637c01870248a6f4ea5b214a59a92a36f18151739452c"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:6b0e029353361f1746bac2e4cc19b32f972ec03f0f943b390c4ab3371840aabf"}, + {file = "aiohttp-3.9.3-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:7cf5c9458e1e90e3c390c2639f1017a0379a99a94fdfad3a1fd966a2874bba52"}, + {file = "aiohttp-3.9.3-cp310-cp310-win32.whl", hash = "sha256:3e59c23c52765951b69ec45ddbbc9403a8761ee6f57253250c6e1536cacc758b"}, + {file = "aiohttp-3.9.3-cp310-cp310-win_amd64.whl", hash = "sha256:055ce4f74b82551678291473f66dc9fb9048a50d8324278751926ff0ae7715e5"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:6b88f9386ff1ad91ace19d2a1c0225896e28815ee09fc6a8932fded8cda97c3d"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c46956ed82961e31557b6857a5ca153c67e5476972e5f7190015018760938da2"}, + {file = "aiohttp-3.9.3-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:07b837ef0d2f252f96009e9b8435ec1fef68ef8b1461933253d318748ec1acdc"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dad46e6f620574b3b4801c68255492e0159d1712271cc99d8bdf35f2043ec266"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5ed3e046ea7b14938112ccd53d91c1539af3e6679b222f9469981e3dac7ba1ce"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:039df344b45ae0b34ac885ab5b53940b174530d4dd8a14ed8b0e2155b9dddccb"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7943c414d3a8d9235f5f15c22ace69787c140c80b718dcd57caaade95f7cd93b"}, + {file = "aiohttp-3.9.3-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:84871a243359bb42c12728f04d181a389718710129b36b6aad0fc4655a7647d4"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:5eafe2c065df5401ba06821b9a054d9cb2848867f3c59801b5d07a0be3a380ae"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:9d3c9b50f19704552f23b4eaea1fc082fdd82c63429a6506446cbd8737823da3"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:f033d80bc6283092613882dfe40419c6a6a1527e04fc69350e87a9df02bbc283"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:2c895a656dd7e061b2fd6bb77d971cc38f2afc277229ce7dd3552de8313a483e"}, + {file = "aiohttp-3.9.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:1f5a71d25cd8106eab05f8704cd9167b6e5187bcdf8f090a66c6d88b634802b4"}, + {file = "aiohttp-3.9.3-cp311-cp311-win32.whl", hash = "sha256:50fca156d718f8ced687a373f9e140c1bb765ca16e3d6f4fe116e3df7c05b2c5"}, + {file = "aiohttp-3.9.3-cp311-cp311-win_amd64.whl", hash = "sha256:5fe9ce6c09668063b8447f85d43b8d1c4e5d3d7e92c63173e6180b2ac5d46dd8"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:38a19bc3b686ad55804ae931012f78f7a534cce165d089a2059f658f6c91fa60"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:770d015888c2a598b377bd2f663adfd947d78c0124cfe7b959e1ef39f5b13869"}, + {file = "aiohttp-3.9.3-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:ee43080e75fc92bf36219926c8e6de497f9b247301bbf88c5c7593d931426679"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:52df73f14ed99cee84865b95a3d9e044f226320a87af208f068ecc33e0c35b96"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:dc9b311743a78043b26ffaeeb9715dc360335e5517832f5a8e339f8a43581e4d"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b955ed993491f1a5da7f92e98d5dad3c1e14dc175f74517c4e610b1f2456fb11"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:504b6981675ace64c28bf4a05a508af5cde526e36492c98916127f5a02354d53"}, + {file = "aiohttp-3.9.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6fe5571784af92b6bc2fda8d1925cccdf24642d49546d3144948a6a1ed58ca5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:ba39e9c8627edc56544c8628cc180d88605df3892beeb2b94c9bc857774848ca"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:e5e46b578c0e9db71d04c4b506a2121c0cb371dd89af17a0586ff6769d4c58c1"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:938a9653e1e0c592053f815f7028e41a3062e902095e5a7dc84617c87267ebd5"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:c3452ea726c76e92f3b9fae4b34a151981a9ec0a4847a627c43d71a15ac32aa6"}, + {file = "aiohttp-3.9.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ff30218887e62209942f91ac1be902cc80cddb86bf00fbc6783b7a43b2bea26f"}, + {file = "aiohttp-3.9.3-cp312-cp312-win32.whl", hash = "sha256:38f307b41e0bea3294a9a2a87833191e4bcf89bb0365e83a8be3a58b31fb7f38"}, + {file = "aiohttp-3.9.3-cp312-cp312-win_amd64.whl", hash = "sha256:b791a3143681a520c0a17e26ae7465f1b6f99461a28019d1a2f425236e6eedb5"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:0ed621426d961df79aa3b963ac7af0d40392956ffa9be022024cd16297b30c8c"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:7f46acd6a194287b7e41e87957bfe2ad1ad88318d447caf5b090012f2c5bb528"}, + {file = "aiohttp-3.9.3-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:feeb18a801aacb098220e2c3eea59a512362eb408d4afd0c242044c33ad6d542"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:f734e38fd8666f53da904c52a23ce517f1b07722118d750405af7e4123933511"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b40670ec7e2156d8e57f70aec34a7216407848dfe6c693ef131ddf6e76feb672"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:fdd215b7b7fd4a53994f238d0f46b7ba4ac4c0adb12452beee724ddd0743ae5d"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:017a21b0df49039c8f46ca0971b3a7fdc1f56741ab1240cb90ca408049766168"}, + {file = "aiohttp-3.9.3-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e99abf0bba688259a496f966211c49a514e65afa9b3073a1fcee08856e04425b"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:648056db9a9fa565d3fa851880f99f45e3f9a771dd3ff3bb0c048ea83fb28194"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:8aacb477dc26797ee089721536a292a664846489c49d3ef9725f992449eda5a8"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:522a11c934ea660ff8953eda090dcd2154d367dec1ae3c540aff9f8a5c109ab4"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:5bce0dc147ca85caa5d33debc4f4d65e8e8b5c97c7f9f660f215fa74fc49a321"}, + {file = "aiohttp-3.9.3-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b4af9f25b49a7be47c0972139e59ec0e8285c371049df1a63b6ca81fdd216a2"}, + {file = "aiohttp-3.9.3-cp38-cp38-win32.whl", hash = "sha256:298abd678033b8571995650ccee753d9458dfa0377be4dba91e4491da3f2be63"}, + {file = "aiohttp-3.9.3-cp38-cp38-win_amd64.whl", hash = "sha256:69361bfdca5468c0488d7017b9b1e5ce769d40b46a9f4a2eed26b78619e9396c"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:0fa43c32d1643f518491d9d3a730f85f5bbaedcbd7fbcae27435bb8b7a061b29"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:835a55b7ca49468aaaac0b217092dfdff370e6c215c9224c52f30daaa735c1c1"}, + {file = "aiohttp-3.9.3-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:06a9b2c8837d9a94fae16c6223acc14b4dfdff216ab9b7202e07a9a09541168f"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:abf151955990d23f84205286938796c55ff11bbfb4ccfada8c9c83ae6b3c89a3"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:59c26c95975f26e662ca78fdf543d4eeaef70e533a672b4113dd888bd2423caa"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:f95511dd5d0e05fd9728bac4096319f80615aaef4acbecb35a990afebe953b0e"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:595f105710293e76b9dc09f52e0dd896bd064a79346234b521f6b968ffdd8e58"}, + {file = "aiohttp-3.9.3-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c7c8b816c2b5af5c8a436df44ca08258fc1a13b449393a91484225fcb7545533"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f1088fa100bf46e7b398ffd9904f4808a0612e1d966b4aa43baa535d1b6341eb"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:f59dfe57bb1ec82ac0698ebfcdb7bcd0e99c255bd637ff613760d5f33e7c81b3"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:361a1026c9dd4aba0109e4040e2aecf9884f5cfe1b1b1bd3d09419c205e2e53d"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:363afe77cfcbe3a36353d8ea133e904b108feea505aa4792dad6585a8192c55a"}, + {file = "aiohttp-3.9.3-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8e2c45c208c62e955e8256949eb225bd8b66a4c9b6865729a786f2aa79b72e9d"}, + {file = "aiohttp-3.9.3-cp39-cp39-win32.whl", hash = "sha256:f7217af2e14da0856e082e96ff637f14ae45c10a5714b63c77f26d8884cf1051"}, + {file = "aiohttp-3.9.3-cp39-cp39-win_amd64.whl", hash = "sha256:27468897f628c627230dba07ec65dc8d0db566923c48f29e084ce382119802bc"}, + {file = "aiohttp-3.9.3.tar.gz", hash = "sha256:90842933e5d1ff760fae6caca4b2b3edba53ba8f4b71e95dacf2818a2aca06f7"}, ] [package.dependencies] @@ -347,13 +347,13 @@ files = [ [[package]] name = "botocore" -version = "1.34.26" +version = "1.34.35" description = "Low-level, data-driven core of boto 3." optional = false python-versions = ">= 3.8" files = [ - {file = "botocore-1.34.26-py3-none-any.whl", hash = "sha256:4f3df0f6ed722e944d6f0eed964bc00b6489e50c6e8d5fdbbb68eb0c6c16c7c9"}, - {file = "botocore-1.34.26.tar.gz", hash = "sha256:63543102467b3b5ba73903f11a14c3157ee442a360f3cb2f5316a8d6bc3e10e7"}, + {file = "botocore-1.34.35-py3-none-any.whl", hash = "sha256:b67b8c865973202dc655a493317ae14b33d115e49ed6960874eb05d950167b37"}, + {file = "botocore-1.34.35.tar.gz", hash = "sha256:8a2b53ab772584a5f7e2fe1e4a59028b0602cfef8e39d622db7c6b670e4b1ee6"}, ] [package.dependencies] @@ -453,13 +453,13 @@ ujson = ["ujson (>=5.7.0)"] [[package]] name = "certifi" -version = "2023.11.17" +version = "2024.2.2" description = "Python package for providing Mozilla's CA Bundle." optional = false python-versions = ">=3.6" files = [ - {file = "certifi-2023.11.17-py3-none-any.whl", hash = "sha256:e036ab49d5b79556f99cfc2d9320b34cfbe5be05c5871b51de9329f0603b0474"}, - {file = "certifi-2023.11.17.tar.gz", hash = "sha256:9b469f3a900bf28dc19b8cfbf8019bf47f7fdd1a65a1d4ffb98fc14166beb4d1"}, + {file = "certifi-2024.2.2-py3-none-any.whl", hash = "sha256:dc383c07b76109f368f6106eee2b593b04a011ea4d55f652c6ca24a754d1cdd1"}, + {file = "certifi-2024.2.2.tar.gz", hash = "sha256:0569859f95fc761b18b45ef421b1290a0f65f147e92a1e5eb3e635f9a5e4e66f"}, ] [[package]] @@ -726,13 +726,13 @@ files = [ [[package]] name = "colorlog" -version = "6.8.0" +version = "6.8.2" description = "Add colours to the output of Python's logging module." optional = false python-versions = ">=3.6" files = [ - {file = "colorlog-6.8.0-py3-none-any.whl", hash = "sha256:4ed23b05a1154294ac99f511fabe8c1d6d4364ec1f7fc989c7fb515ccc29d375"}, - {file = "colorlog-6.8.0.tar.gz", hash = "sha256:fbb6fdf9d5685f2517f388fb29bb27d54e8654dd31f58bc2a3b217e967a95ca6"}, + {file = "colorlog-6.8.2-py3-none-any.whl", hash = "sha256:4dcbb62368e2800cb3c5abd348da7e53f6c362dda502ec27c560b2e58a66bd33"}, + {file = "colorlog-6.8.2.tar.gz", hash = "sha256:3e3e079a41feb5a1b64f978b5ea4f46040a94f11f0e8bbb8261e3dbbeca64d44"}, ] [package.dependencies] @@ -754,63 +754,63 @@ files = [ [[package]] name = "coverage" -version = "7.4.0" +version = "7.4.1" description = "Code coverage measurement for Python" optional = false python-versions = ">=3.8" files = [ - {file = "coverage-7.4.0-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:36b0ea8ab20d6a7564e89cb6135920bc9188fb5f1f7152e94e8300b7b189441a"}, - {file = "coverage-7.4.0-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0676cd0ba581e514b7f726495ea75aba3eb20899d824636c6f59b0ed2f88c471"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d0ca5c71a5a1765a0f8f88022c52b6b8be740e512980362f7fdbb03725a0d6b9"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a7c97726520f784239f6c62506bc70e48d01ae71e9da128259d61ca5e9788516"}, - {file = "coverage-7.4.0-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:815ac2d0f3398a14286dc2cea223a6f338109f9ecf39a71160cd1628786bc6f5"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:80b5ee39b7f0131ebec7968baa9b2309eddb35b8403d1869e08f024efd883566"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:5b2ccb7548a0b65974860a78c9ffe1173cfb5877460e5a229238d985565574ae"}, - {file = "coverage-7.4.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:995ea5c48c4ebfd898eacb098164b3cc826ba273b3049e4a889658548e321b43"}, - {file = "coverage-7.4.0-cp310-cp310-win32.whl", hash = "sha256:79287fd95585ed36e83182794a57a46aeae0b64ca53929d1176db56aacc83451"}, - {file = "coverage-7.4.0-cp310-cp310-win_amd64.whl", hash = "sha256:5b14b4f8760006bfdb6e08667af7bc2d8d9bfdb648351915315ea17645347137"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:04387a4a6ecb330c1878907ce0dc04078ea72a869263e53c72a1ba5bbdf380ca"}, - {file = "coverage-7.4.0-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ea81d8f9691bb53f4fb4db603203029643caffc82bf998ab5b59ca05560f4c06"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:74775198b702868ec2d058cb92720a3c5a9177296f75bd97317c787daf711505"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76f03940f9973bfaee8cfba70ac991825611b9aac047e5c80d499a44079ec0bc"}, - {file = "coverage-7.4.0-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:485e9f897cf4856a65a57c7f6ea3dc0d4e6c076c87311d4bc003f82cfe199d25"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6ae8c9d301207e6856865867d762a4b6fd379c714fcc0607a84b92ee63feff70"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:bf477c355274a72435ceb140dc42de0dc1e1e0bf6e97195be30487d8eaaf1a09"}, - {file = "coverage-7.4.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:83c2dda2666fe32332f8e87481eed056c8b4d163fe18ecc690b02802d36a4d26"}, - {file = "coverage-7.4.0-cp311-cp311-win32.whl", hash = "sha256:697d1317e5290a313ef0d369650cfee1a114abb6021fa239ca12b4849ebbd614"}, - {file = "coverage-7.4.0-cp311-cp311-win_amd64.whl", hash = "sha256:26776ff6c711d9d835557ee453082025d871e30b3fd6c27fcef14733f67f0590"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:13eaf476ec3e883fe3e5fe3707caeb88268a06284484a3daf8250259ef1ba143"}, - {file = "coverage-7.4.0-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:846f52f46e212affb5bcf131c952fb4075b55aae6b61adc9856222df89cbe3e2"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:26f66da8695719ccf90e794ed567a1549bb2644a706b41e9f6eae6816b398c4a"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:164fdcc3246c69a6526a59b744b62e303039a81e42cfbbdc171c91a8cc2f9446"}, - {file = "coverage-7.4.0-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:316543f71025a6565677d84bc4df2114e9b6a615aa39fb165d697dba06a54af9"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:bb1de682da0b824411e00a0d4da5a784ec6496b6850fdf8c865c1d68c0e318dd"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:0e8d06778e8fbffccfe96331a3946237f87b1e1d359d7fbe8b06b96c95a5407a"}, - {file = "coverage-7.4.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:a56de34db7b7ff77056a37aedded01b2b98b508227d2d0979d373a9b5d353daa"}, - {file = "coverage-7.4.0-cp312-cp312-win32.whl", hash = "sha256:51456e6fa099a8d9d91497202d9563a320513fcf59f33991b0661a4a6f2ad450"}, - {file = "coverage-7.4.0-cp312-cp312-win_amd64.whl", hash = "sha256:cd3c1e4cb2ff0083758f09be0f77402e1bdf704adb7f89108007300a6da587d0"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:e9d1bf53c4c8de58d22e0e956a79a5b37f754ed1ffdbf1a260d9dcfa2d8a325e"}, - {file = "coverage-7.4.0-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:109f5985182b6b81fe33323ab4707011875198c41964f014579cf82cebf2bb85"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3cc9d4bc55de8003663ec94c2f215d12d42ceea128da8f0f4036235a119c88ac"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cc6d65b21c219ec2072c1293c505cf36e4e913a3f936d80028993dd73c7906b1"}, - {file = "coverage-7.4.0-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:5a10a4920def78bbfff4eff8a05c51be03e42f1c3735be42d851f199144897ba"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:b8e99f06160602bc64da35158bb76c73522a4010f0649be44a4e167ff8555952"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7d360587e64d006402b7116623cebf9d48893329ef035278969fa3bbf75b697e"}, - {file = "coverage-7.4.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:29f3abe810930311c0b5d1a7140f6395369c3db1be68345638c33eec07535105"}, - {file = "coverage-7.4.0-cp38-cp38-win32.whl", hash = "sha256:5040148f4ec43644702e7b16ca864c5314ccb8ee0751ef617d49aa0e2d6bf4f2"}, - {file = "coverage-7.4.0-cp38-cp38-win_amd64.whl", hash = "sha256:9864463c1c2f9cb3b5db2cf1ff475eed2f0b4285c2aaf4d357b69959941aa555"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:936d38794044b26c99d3dd004d8af0035ac535b92090f7f2bb5aa9c8e2f5cd42"}, - {file = "coverage-7.4.0-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:799c8f873794a08cdf216aa5d0531c6a3747793b70c53f70e98259720a6fe2d7"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e7defbb9737274023e2d7af02cac77043c86ce88a907c58f42b580a97d5bcca9"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a1526d265743fb49363974b7aa8d5899ff64ee07df47dd8d3e37dcc0818f09ed"}, - {file = "coverage-7.4.0-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:bf635a52fc1ea401baf88843ae8708591aa4adff875e5c23220de43b1ccf575c"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:756ded44f47f330666843b5781be126ab57bb57c22adbb07d83f6b519783b870"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:0eb3c2f32dabe3a4aaf6441dde94f35687224dfd7eb2a7f47f3fd9428e421058"}, - {file = "coverage-7.4.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:bfd5db349d15c08311702611f3dccbef4b4e2ec148fcc636cf8739519b4a5c0f"}, - {file = "coverage-7.4.0-cp39-cp39-win32.whl", hash = "sha256:53d7d9158ee03956e0eadac38dfa1ec8068431ef8058fe6447043db1fb40d932"}, - {file = "coverage-7.4.0-cp39-cp39-win_amd64.whl", hash = "sha256:cfd2a8b6b0d8e66e944d47cdec2f47c48fef2ba2f2dff5a9a75757f64172857e"}, - {file = "coverage-7.4.0-pp38.pp39.pp310-none-any.whl", hash = "sha256:c530833afc4707fe48524a44844493f36d8727f04dcce91fb978c414a8556cc6"}, - {file = "coverage-7.4.0.tar.gz", hash = "sha256:707c0f58cb1712b8809ece32b68996ee1e609f71bd14615bd8f87a1293cb610e"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:077d366e724f24fc02dbfe9d946534357fda71af9764ff99d73c3c596001bbd7"}, + {file = "coverage-7.4.1-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:0193657651f5399d433c92f8ae264aff31fc1d066deee4b831549526433f3f61"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:d17bbc946f52ca67adf72a5ee783cd7cd3477f8f8796f59b4974a9b59cacc9ee"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a3277f5fa7483c927fe3a7b017b39351610265308f5267ac6d4c2b64cc1d8d25"}, + {file = "coverage-7.4.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:6dceb61d40cbfcf45f51e59933c784a50846dc03211054bd76b421a713dcdf19"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6008adeca04a445ea6ef31b2cbaf1d01d02986047606f7da266629afee982630"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:c61f66d93d712f6e03369b6a7769233bfda880b12f417eefdd4f16d1deb2fc4c"}, + {file = "coverage-7.4.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:b9bb62fac84d5f2ff523304e59e5c439955fb3b7f44e3d7b2085184db74d733b"}, + {file = "coverage-7.4.1-cp310-cp310-win32.whl", hash = "sha256:f86f368e1c7ce897bf2457b9eb61169a44e2ef797099fb5728482b8d69f3f016"}, + {file = "coverage-7.4.1-cp310-cp310-win_amd64.whl", hash = "sha256:869b5046d41abfea3e381dd143407b0d29b8282a904a19cb908fa24d090cc018"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:b8ffb498a83d7e0305968289441914154fb0ef5d8b3157df02a90c6695978295"}, + {file = "coverage-7.4.1-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:3cacfaefe6089d477264001f90f55b7881ba615953414999c46cc9713ff93c8c"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5d6850e6e36e332d5511a48a251790ddc545e16e8beaf046c03985c69ccb2676"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:18e961aa13b6d47f758cc5879383d27b5b3f3dcd9ce8cdbfdc2571fe86feb4dd"}, + {file = "coverage-7.4.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dfd1e1b9f0898817babf840b77ce9fe655ecbe8b1b327983df485b30df8cc011"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:6b00e21f86598b6330f0019b40fb397e705135040dbedc2ca9a93c7441178e74"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:536d609c6963c50055bab766d9951b6c394759190d03311f3e9fcf194ca909e1"}, + {file = "coverage-7.4.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:7ac8f8eb153724f84885a1374999b7e45734bf93a87d8df1e7ce2146860edef6"}, + {file = "coverage-7.4.1-cp311-cp311-win32.whl", hash = "sha256:f3771b23bb3675a06f5d885c3630b1d01ea6cac9e84a01aaf5508706dba546c5"}, + {file = "coverage-7.4.1-cp311-cp311-win_amd64.whl", hash = "sha256:9d2f9d4cc2a53b38cabc2d6d80f7f9b7e3da26b2f53d48f05876fef7956b6968"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:f68ef3660677e6624c8cace943e4765545f8191313a07288a53d3da188bd8581"}, + {file = "coverage-7.4.1-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:23b27b8a698e749b61809fb637eb98ebf0e505710ec46a8aa6f1be7dc0dc43a6"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:3e3424c554391dc9ef4a92ad28665756566a28fecf47308f91841f6c49288e66"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e0860a348bf7004c812c8368d1fc7f77fe8e4c095d661a579196a9533778e156"}, + {file = "coverage-7.4.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe558371c1bdf3b8fa03e097c523fb9645b8730399c14fe7721ee9c9e2a545d3"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3468cc8720402af37b6c6e7e2a9cdb9f6c16c728638a2ebc768ba1ef6f26c3a1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:02f2edb575d62172aa28fe00efe821ae31f25dc3d589055b3fb64d51e52e4ab1"}, + {file = "coverage-7.4.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ca6e61dc52f601d1d224526360cdeab0d0712ec104a2ce6cc5ccef6ed9a233bc"}, + {file = "coverage-7.4.1-cp312-cp312-win32.whl", hash = "sha256:ca7b26a5e456a843b9b6683eada193fc1f65c761b3a473941efe5a291f604c74"}, + {file = "coverage-7.4.1-cp312-cp312-win_amd64.whl", hash = "sha256:85ccc5fa54c2ed64bd91ed3b4a627b9cce04646a659512a051fa82a92c04a448"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:8bdb0285a0202888d19ec6b6d23d5990410decb932b709f2b0dfe216d031d218"}, + {file = "coverage-7.4.1-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:918440dea04521f499721c039863ef95433314b1db00ff826a02580c1f503e45"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:379d4c7abad5afbe9d88cc31ea8ca262296480a86af945b08214eb1a556a3e4d"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b094116f0b6155e36a304ff912f89bbb5067157aff5f94060ff20bbabdc8da06"}, + {file = "coverage-7.4.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:f2f5968608b1fe2a1d00d01ad1017ee27efd99b3437e08b83ded9b7af3f6f766"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:10e88e7f41e6197ea0429ae18f21ff521d4f4490aa33048f6c6f94c6045a6a75"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a4a3907011d39dbc3e37bdc5df0a8c93853c369039b59efa33a7b6669de04c60"}, + {file = "coverage-7.4.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:6d224f0c4c9c98290a6990259073f496fcec1b5cc613eecbd22786d398ded3ad"}, + {file = "coverage-7.4.1-cp38-cp38-win32.whl", hash = "sha256:23f5881362dcb0e1a92b84b3c2809bdc90db892332daab81ad8f642d8ed55042"}, + {file = "coverage-7.4.1-cp38-cp38-win_amd64.whl", hash = "sha256:a07f61fc452c43cd5328b392e52555f7d1952400a1ad09086c4a8addccbd138d"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:8e738a492b6221f8dcf281b67129510835461132b03024830ac0e554311a5c54"}, + {file = "coverage-7.4.1-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:46342fed0fff72efcda77040b14728049200cbba1279e0bf1188f1f2078c1d70"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9641e21670c68c7e57d2053ddf6c443e4f0a6e18e547e86af3fad0795414a628"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:aeb2c2688ed93b027eb0d26aa188ada34acb22dceea256d76390eea135083950"}, + {file = "coverage-7.4.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d12c923757de24e4e2110cf8832d83a886a4cf215c6e61ed506006872b43a6d1"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:0491275c3b9971cdbd28a4595c2cb5838f08036bca31765bad5e17edf900b2c7"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:8dfc5e195bbef80aabd81596ef52a1277ee7143fe419efc3c4d8ba2754671756"}, + {file = "coverage-7.4.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:1a78b656a4d12b0490ca72651fe4d9f5e07e3c6461063a9b6265ee45eb2bdd35"}, + {file = "coverage-7.4.1-cp39-cp39-win32.whl", hash = "sha256:f90515974b39f4dea2f27c0959688621b46d96d5a626cf9c53dbc653a895c05c"}, + {file = "coverage-7.4.1-cp39-cp39-win_amd64.whl", hash = "sha256:64e723ca82a84053dd7bfcc986bdb34af8d9da83c521c19d6b472bc6880e191a"}, + {file = "coverage-7.4.1-pp38.pp39.pp310-none-any.whl", hash = "sha256:32a8d985462e37cfdab611a6f95b09d7c091d07668fdc26e47a725ee575fe166"}, + {file = "coverage-7.4.1.tar.gz", hash = "sha256:1ed4b95480952b1a26d863e546fa5094564aa0065e1e5f0d4d0041f293251d04"}, ] [package.dependencies] @@ -832,43 +832,43 @@ files = [ [[package]] name = "cryptography" -version = "42.0.0" +version = "42.0.2" description = "cryptography is a package which provides cryptographic recipes and primitives to Python developers." optional = false python-versions = ">=3.7" files = [ - {file = "cryptography-42.0.0-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:c640b0ef54138fde761ec99a6c7dc4ce05e80420262c20fa239e694ca371d434"}, - {file = "cryptography-42.0.0-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:678cfa0d1e72ef41d48993a7be75a76b0725d29b820ff3cfd606a5b2b33fda01"}, - {file = "cryptography-42.0.0-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:146e971e92a6dd042214b537a726c9750496128453146ab0ee8971a0299dc9bd"}, - {file = "cryptography-42.0.0-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:87086eae86a700307b544625e3ba11cc600c3c0ef8ab97b0fda0705d6db3d4e3"}, - {file = "cryptography-42.0.0-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:0a68bfcf57a6887818307600c3c0ebc3f62fbb6ccad2240aa21887cda1f8df1b"}, - {file = "cryptography-42.0.0-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:5a217bca51f3b91971400890905a9323ad805838ca3fa1e202a01844f485ee87"}, - {file = "cryptography-42.0.0-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:ca20550bb590db16223eb9ccc5852335b48b8f597e2f6f0878bbfd9e7314eb17"}, - {file = "cryptography-42.0.0-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:33588310b5c886dfb87dba5f013b8d27df7ffd31dc753775342a1e5ab139e59d"}, - {file = "cryptography-42.0.0-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:9515ea7f596c8092fdc9902627e51b23a75daa2c7815ed5aa8cf4f07469212ec"}, - {file = "cryptography-42.0.0-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:35cf6ed4c38f054478a9df14f03c1169bb14bd98f0b1705751079b25e1cb58bc"}, - {file = "cryptography-42.0.0-cp37-abi3-win32.whl", hash = "sha256:8814722cffcfd1fbd91edd9f3451b88a8f26a5fd41b28c1c9193949d1c689dc4"}, - {file = "cryptography-42.0.0-cp37-abi3-win_amd64.whl", hash = "sha256:a2a8d873667e4fd2f34aedab02ba500b824692c6542e017075a2efc38f60a4c0"}, - {file = "cryptography-42.0.0-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:8fedec73d590fd30c4e3f0d0f4bc961aeca8390c72f3eaa1a0874d180e868ddf"}, - {file = "cryptography-42.0.0-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:be41b0c7366e5549265adf2145135dca107718fa44b6e418dc7499cfff6b4689"}, - {file = "cryptography-42.0.0-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ca482ea80626048975360c8e62be3ceb0f11803180b73163acd24bf014133a0"}, - {file = "cryptography-42.0.0-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:c58115384bdcfe9c7f644c72f10f6f42bed7cf59f7b52fe1bf7ae0a622b3a139"}, - {file = "cryptography-42.0.0-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:56ce0c106d5c3fec1038c3cca3d55ac320a5be1b44bf15116732d0bc716979a2"}, - {file = "cryptography-42.0.0-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:324721d93b998cb7367f1e6897370644751e5580ff9b370c0a50dc60a2003513"}, - {file = "cryptography-42.0.0-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:d97aae66b7de41cdf5b12087b5509e4e9805ed6f562406dfcf60e8481a9a28f8"}, - {file = "cryptography-42.0.0-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:85f759ed59ffd1d0baad296e72780aa62ff8a71f94dc1ab340386a1207d0ea81"}, - {file = "cryptography-42.0.0-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:206aaf42e031b93f86ad60f9f5d9da1b09164f25488238ac1dc488334eb5e221"}, - {file = "cryptography-42.0.0-cp39-abi3-win32.whl", hash = "sha256:74f18a4c8ca04134d2052a140322002fef535c99cdbc2a6afc18a8024d5c9d5b"}, - {file = "cryptography-42.0.0-cp39-abi3-win_amd64.whl", hash = "sha256:14e4b909373bc5bf1095311fa0f7fcabf2d1a160ca13f1e9e467be1ac4cbdf94"}, - {file = "cryptography-42.0.0-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:3005166a39b70c8b94455fdbe78d87a444da31ff70de3331cdec2c568cf25b7e"}, - {file = "cryptography-42.0.0-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:be14b31eb3a293fc6e6aa2807c8a3224c71426f7c4e3639ccf1a2f3ffd6df8c3"}, - {file = "cryptography-42.0.0-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:bd7cf7a8d9f34cc67220f1195884151426ce616fdc8285df9054bfa10135925f"}, - {file = "cryptography-42.0.0-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:c310767268d88803b653fffe6d6f2f17bb9d49ffceb8d70aed50ad45ea49ab08"}, - {file = "cryptography-42.0.0-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:bdce70e562c69bb089523e75ef1d9625b7417c6297a76ac27b1b8b1eb51b7d0f"}, - {file = "cryptography-42.0.0-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:e9326ca78111e4c645f7e49cbce4ed2f3f85e17b61a563328c85a5208cf34440"}, - {file = "cryptography-42.0.0-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:69fd009a325cad6fbfd5b04c711a4da563c6c4854fc4c9544bff3088387c77c0"}, - {file = "cryptography-42.0.0-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:988b738f56c665366b1e4bfd9045c3efae89ee366ca3839cd5af53eaa1401bce"}, - {file = "cryptography-42.0.0.tar.gz", hash = "sha256:6cf9b76d6e93c62114bd19485e5cb003115c134cf9ce91f8ac924c44f8c8c3f4"}, + {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_universal2.whl", hash = "sha256:701171f825dcab90969596ce2af253143b93b08f1a716d4b2a9d2db5084ef7be"}, + {file = "cryptography-42.0.2-cp37-abi3-macosx_10_12_x86_64.whl", hash = "sha256:61321672b3ac7aade25c40449ccedbc6db72c7f5f0fdf34def5e2f8b51ca530d"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea2c3ffb662fec8bbbfce5602e2c159ff097a4631d96235fcf0fb00e59e3ece4"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3b15c678f27d66d247132cbf13df2f75255627bcc9b6a570f7d2fd08e8c081d2"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:8e88bb9eafbf6a4014d55fb222e7360eef53e613215085e65a13290577394529"}, + {file = "cryptography-42.0.2-cp37-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:a047682d324ba56e61b7ea7c7299d51e61fd3bca7dad2ccc39b72bd0118d60a1"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:36d4b7c4be6411f58f60d9ce555a73df8406d484ba12a63549c88bd64f7967f1"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:a00aee5d1b6c20620161984f8ab2ab69134466c51f58c052c11b076715e72929"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:b97fe7d7991c25e6a31e5d5e795986b18fbbb3107b873d5f3ae6dc9a103278e9"}, + {file = "cryptography-42.0.2-cp37-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:5fa82a26f92871eca593b53359c12ad7949772462f887c35edaf36f87953c0e2"}, + {file = "cryptography-42.0.2-cp37-abi3-win32.whl", hash = "sha256:4b063d3413f853e056161eb0c7724822a9740ad3caa24b8424d776cebf98e7ee"}, + {file = "cryptography-42.0.2-cp37-abi3-win_amd64.whl", hash = "sha256:841ec8af7a8491ac76ec5a9522226e287187a3107e12b7d686ad354bb78facee"}, + {file = "cryptography-42.0.2-cp39-abi3-macosx_10_12_universal2.whl", hash = "sha256:55d1580e2d7e17f45d19d3b12098e352f3a37fe86d380bf45846ef257054b242"}, + {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:28cb2c41f131a5758d6ba6a0504150d644054fd9f3203a1e8e8d7ac3aea7f73a"}, + {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b9097a208875fc7bbeb1286d0125d90bdfed961f61f214d3f5be62cd4ed8a446"}, + {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_aarch64.whl", hash = "sha256:44c95c0e96b3cb628e8452ec060413a49002a247b2b9938989e23a2c8291fc90"}, + {file = "cryptography-42.0.2-cp39-abi3-manylinux_2_28_x86_64.whl", hash = "sha256:2f9f14185962e6a04ab32d1abe34eae8a9001569ee4edb64d2304bf0d65c53f3"}, + {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_aarch64.whl", hash = "sha256:09a77e5b2e8ca732a19a90c5bca2d124621a1edb5438c5daa2d2738bfeb02589"}, + {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_1_x86_64.whl", hash = "sha256:ad28cff53f60d99a928dfcf1e861e0b2ceb2bc1f08a074fdd601b314e1cc9e0a"}, + {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_aarch64.whl", hash = "sha256:130c0f77022b2b9c99d8cebcdd834d81705f61c68e91ddd614ce74c657f8b3ea"}, + {file = "cryptography-42.0.2-cp39-abi3-musllinux_1_2_x86_64.whl", hash = "sha256:fa3dec4ba8fb6e662770b74f62f1a0c7d4e37e25b58b2bf2c1be4c95372b4a33"}, + {file = "cryptography-42.0.2-cp39-abi3-win32.whl", hash = "sha256:3dbd37e14ce795b4af61b89b037d4bc157f2cb23e676fa16932185a04dfbf635"}, + {file = "cryptography-42.0.2-cp39-abi3-win_amd64.whl", hash = "sha256:8a06641fb07d4e8f6c7dda4fc3f8871d327803ab6542e33831c7ccfdcb4d0ad6"}, + {file = "cryptography-42.0.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:087887e55e0b9c8724cf05361357875adb5c20dec27e5816b653492980d20380"}, + {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:a7ef8dd0bf2e1d0a27042b231a3baac6883cdd5557036f5e8df7139255feaac6"}, + {file = "cryptography-42.0.2-pp310-pypy310_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:4383b47f45b14459cab66048d384614019965ba6c1a1a141f11b5a551cace1b2"}, + {file = "cryptography-42.0.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:fbeb725c9dc799a574518109336acccaf1303c30d45c075c665c0793c2f79a7f"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:320948ab49883557a256eab46149df79435a22d2fefd6a66fe6946f1b9d9d008"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_aarch64.whl", hash = "sha256:5ef9bc3d046ce83c4bbf4c25e1e0547b9c441c01d30922d812e887dc5f125c12"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-manylinux_2_28_x86_64.whl", hash = "sha256:52ed9ebf8ac602385126c9a2fe951db36f2cb0c2538d22971487f89d0de4065a"}, + {file = "cryptography-42.0.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:141e2aa5ba100d3788c0ad7919b288f89d1fe015878b9659b307c9ef867d3a65"}, + {file = "cryptography-42.0.2.tar.gz", hash = "sha256:e0ec52ba3c7f1b7d813cd52649a5b3ef1fc0d433219dc8c93827c57eab6cf888"}, ] [package.dependencies] @@ -920,71 +920,71 @@ six = "*" [[package]] name = "ddtrace" -version = "2.5.0" +version = "2.5.2" description = "Datadog APM client library" optional = false python-versions = ">=3.7" files = [ - {file = "ddtrace-2.5.0-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:87b29471859ac7342a8f3059bbcb5009f14a85484fafd9514cf1098a4fa833fd"}, - {file = "ddtrace-2.5.0-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:8dbfb7f9ff937270c300d6e549366d156741fcd4bf7a1ee8b3624eed474ba911"}, - {file = "ddtrace-2.5.0-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:98060971be48a43a101fa3e8cf056272734d2449e1e7719b2d8fc9191e2c2dcd"}, - {file = "ddtrace-2.5.0-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:81a9078199bc681fb1a292e087c481b2eb21174e6c7617bbbb6994965ad9bd3b"}, - {file = "ddtrace-2.5.0-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:915e85496bc6d5dfe5ed07e1d36bf766a7d42eef4cda006b6969adbe0b7d3b0c"}, - {file = "ddtrace-2.5.0-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:cdefefdbf97cc6b5ebf224b7145cb8c8099f459dc5ce21fc1b4076bb63ec83c6"}, - {file = "ddtrace-2.5.0-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:f0b22cb0d5f008107771f8949b4cded1b1e9415d6a914e16a603f1bb9c149a79"}, - {file = "ddtrace-2.5.0-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:be6f378a2053ec763814a3c9fbb75c56576ddb63ebf34c2a12a1b2ba4af83012"}, - {file = "ddtrace-2.5.0-cp310-cp310-win32.whl", hash = "sha256:9c125308abf36d5904a67fb08fb6169d6485c353bf69c539101f98ad6b2a368e"}, - {file = "ddtrace-2.5.0-cp310-cp310-win_amd64.whl", hash = "sha256:9c891666797675617eaa9fec1b8e7e6fbb5728e21c931185c3d944bc0920f860"}, - {file = "ddtrace-2.5.0-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:65365f8b8a6821d4d04b92906db1ae90a7244fa4fdfdee7c3db12985ce40eee0"}, - {file = "ddtrace-2.5.0-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:576eee349861acd19f41052043e146a4122d70ae6ff7dbdeef9236ae14eb05f8"}, - {file = "ddtrace-2.5.0-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5c7e4d2f34f1ca37afe3cc935b8369fee7e9a9c7914bd321a395189fca503f24"}, - {file = "ddtrace-2.5.0-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b9905c2323de5db1b8b28bfd8bdf11a145ae89c4e16230ea229da0d40ea3bf35"}, - {file = "ddtrace-2.5.0-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:259eee688f30cbaa203bb7b0eb708acf64a0f94add7c57497fe46dead5c978a8"}, - {file = "ddtrace-2.5.0-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:19bbd1ddb7a6a14eee38290ad3ba16bbef9ea70a29dc70ac1d43d56f37e7a61c"}, - {file = "ddtrace-2.5.0-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b57ed0b97ac47ffd48870e483c891d105734a611368c66eff22fa4ea7b44e1f6"}, - {file = "ddtrace-2.5.0-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:a9efef80b66e1c4feacb9d935d9b9f39effed6b2144a313d916bd23cfff7554a"}, - {file = "ddtrace-2.5.0-cp311-cp311-win32.whl", hash = "sha256:57d48ed4263592af5c2634166a7143257e8ad07b1dc22f0e4f4a5cc0247fed25"}, - {file = "ddtrace-2.5.0-cp311-cp311-win_amd64.whl", hash = "sha256:40cc73b3722594aea30acf2e63919753549846d0021bd28e91dc9d3b31c65f2a"}, - {file = "ddtrace-2.5.0-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:ad33becc68821225271ae50f854cc5c06ac13156e22f7b845a29bf17363d72ad"}, - {file = "ddtrace-2.5.0-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:da10ba56a9ef0d4d3639a434b59f3c6cad9e76f745b25559d1bdb93bb2c42ac7"}, - {file = "ddtrace-2.5.0-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ad12b6c37533e19f7a9f4152b271a85b95fd11210ad40d90878ae3ddac217933"}, - {file = "ddtrace-2.5.0-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:c2be11cee3c034537be2c89b1082d45d8e5dccc4e2dc85092c27d9c7c567d716"}, - {file = "ddtrace-2.5.0-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:450719d62813c7f6f74cf9866af0267fecdfc478a60c8b0d4dce2527edf0f495"}, - {file = "ddtrace-2.5.0-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3324dc6cdaaa1f67239860fc8da527a380d20fd63b0bef4ad21b4505dad0cad8"}, - {file = "ddtrace-2.5.0-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:ba8ff8c5ff1e8d44fb2bf970f0f8f833f11a4f3f42213481dac81ec316ff8a68"}, - {file = "ddtrace-2.5.0-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:979cb8b644312304e62607e1993f19203e8e9d903cb48a6be482789ef9083f06"}, - {file = "ddtrace-2.5.0-cp312-cp312-win32.whl", hash = "sha256:8008eb92b226a75a4d650f3c6fcc597e971bb73ef706db7ab54ed556c1b39bc2"}, - {file = "ddtrace-2.5.0-cp312-cp312-win_amd64.whl", hash = "sha256:3eb13fe126d2bf6597f323c137255f19d18c629f387f3f276a2084dbb00fa074"}, - {file = "ddtrace-2.5.0-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:f242505b8d4413404f7144de0f10d3e8a5c89bc7cc5f695baa40bc7190a2018b"}, - {file = "ddtrace-2.5.0-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:dee79a60a1cbe263827ba930ae1264019a4c98f15e9f0020b4b64a03302c86e5"}, - {file = "ddtrace-2.5.0-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3399db77465d67c41c178e0ed0a4ec6fc381bb0f30d067f4cbfd31dcd587049f"}, - {file = "ddtrace-2.5.0-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1334e7aac574f2ab887f316e7d1c18507e049fd2dff752f5028fd53b19068096"}, - {file = "ddtrace-2.5.0-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:191c92015456449459fdf99f93daede95ecc4c930f64e42d9266ecb4da459e4d"}, - {file = "ddtrace-2.5.0-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:7f7ff413d6a66d0008ee4b724a98a429431abd5a5c8d7d91696bb7674e019989"}, - {file = "ddtrace-2.5.0-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c06b63834f87192eb29c82a9a8a6e1a89e4aefde4f0c516ec3494769f20b0d9b"}, - {file = "ddtrace-2.5.0-cp37-cp37m-win32.whl", hash = "sha256:4a4e8864915515b1561687dd8b5ef39fa69f2b4143f564ebcbb3fa0ab6467b1b"}, - {file = "ddtrace-2.5.0-cp37-cp37m-win_amd64.whl", hash = "sha256:43b508303b91eee7f2ac4ae725bcc6bec179a5c4793d350fd1d269a1dc3fec5a"}, - {file = "ddtrace-2.5.0-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:e3a8dc9f0e956415b1b7e608adb8aab1e75671eb517589e6650d832e5dd44194"}, - {file = "ddtrace-2.5.0-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:58fe77df98662ae0e47754339d8439a6e9579541507707162cc8550e572f3d44"}, - {file = "ddtrace-2.5.0-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ea9dc8857485cac1956c03257861a4686d98acbd5991408f1c5625ef3519301a"}, - {file = "ddtrace-2.5.0-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:66641f899a11cffeb77685af753097abafac8cd9738ab71e4b180d100ea69eb9"}, - {file = "ddtrace-2.5.0-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:605d190bf8ba887455ddbdae274e70d80819f2f5f8b0a851dbf47baea12753c5"}, - {file = "ddtrace-2.5.0-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:e5158e52a59dfd693465562e32256fb873aeb948672c09351f12cf81aca7e61d"}, - {file = "ddtrace-2.5.0-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:bd654e982ba3b27a23caf21e365ad7dad1b439d3941ccd1d4c94f49672e03cbb"}, - {file = "ddtrace-2.5.0-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:0b52eb7d080223f989d9ad44da3ea112e071dc1a06ae24ac1b40fc497d0a0790"}, - {file = "ddtrace-2.5.0-cp38-cp38-win32.whl", hash = "sha256:aeb8d7a7290ab38565f73aab4ef2fb9e8e89f0fea1df6200c91af0b9a87db137"}, - {file = "ddtrace-2.5.0-cp38-cp38-win_amd64.whl", hash = "sha256:a5e91cf074d0b94650766496f42c29701f23701f2b8d4c0ee6e91fac1fac3dd7"}, - {file = "ddtrace-2.5.0-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:6045fa21d699835ec8f93d8ce50c79b1c8c840de937fc1d5f5e52c3ad504794e"}, - {file = "ddtrace-2.5.0-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:ebc5878e00a0657dc63bac7dbcc5c8b1188cf81b7319a24300045913ba3c3a94"}, - {file = "ddtrace-2.5.0-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0d5ee84f89639e28faec8e77008314b8a280f93fc2071da2c13211dbb5b02769"}, - {file = "ddtrace-2.5.0-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:163d45eb7265af6cf6f1419a36ca10fcc5d2bd6c7dc9480787869c0ef1d24662"}, - {file = "ddtrace-2.5.0-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c220ab1a819aa4efa64fe5a2659bc1439dfa5e93121e137876519c8f2e338512"}, - {file = "ddtrace-2.5.0-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:4e61fc972e2eb5950a717d50ee57d90d512825ef874fc155889c07c60f7e2d75"}, - {file = "ddtrace-2.5.0-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:ea6ca63cf8348e99dbfdba13abebe97aa3e3c6270cc34e40c7415d0eb5a08946"}, - {file = "ddtrace-2.5.0-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:887d31035adfc16f8fd2a04f0814afa6b3ae6f93699e773c0e9d9928c0698153"}, - {file = "ddtrace-2.5.0-cp39-cp39-win32.whl", hash = "sha256:d35413026a93017d4a5ead8fb6794148e797e9664ffb82dbe6f6f78ea9828324"}, - {file = "ddtrace-2.5.0-cp39-cp39-win_amd64.whl", hash = "sha256:5e2a38c5519906dd83d99e2ece6ade2cc577337e164a00fbcb5a3b7dfc957cbb"}, - {file = "ddtrace-2.5.0.tar.gz", hash = "sha256:4e1c992ad76d0b37f07ccfda375679c3d367a1ce0c4540b4112aaad5b5794ae2"}, + {file = "ddtrace-2.5.2-cp310-cp310-macosx_11_0_universal2.whl", hash = "sha256:f918538a6adb33696be653d343ee318b16ea977376d9b7214d14fe97c42e9bd9"}, + {file = "ddtrace-2.5.2-cp310-cp310-macosx_11_0_x86_64.whl", hash = "sha256:f56735eb636d3ab2f7224f261d3a6bd43f884e9901d68407d485ea65f3dc0f46"}, + {file = "ddtrace-2.5.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:72d21fe6842a8d80c8765dd699153a2475ae2d49e82e10f9668eadb08b454040"}, + {file = "ddtrace-2.5.2-cp310-cp310-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:a6e48caf63506d7ac3df7caa955b6258de91c1a1f55149506ab8ac36143770b9"}, + {file = "ddtrace-2.5.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dc3f26e04ba7521f6885d871fd6266fedc0a7ccf2637b85579c058927404bad7"}, + {file = "ddtrace-2.5.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:15d78b0cd5d2090c063031d76e933b8b24e043d524a6091a751cf57b0fab025f"}, + {file = "ddtrace-2.5.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:ee76beaf87695f2204b0c2c2a3664b39f3483b7a8447b28e5e2bcc899861b3eb"}, + {file = "ddtrace-2.5.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:8840f0e82d6dca3888bd06e7ab0ca6d39009f3cd3475028d8bc03c939127afc2"}, + {file = "ddtrace-2.5.2-cp310-cp310-win32.whl", hash = "sha256:a34ccab0c8991c5fc5252d5cd6e88852cd7f77c8bf838de84e70b4a3bfacaad4"}, + {file = "ddtrace-2.5.2-cp310-cp310-win_amd64.whl", hash = "sha256:ffa4f5779c7000fe5960156bd15339184355b30a661b0955799cae50da5d03a7"}, + {file = "ddtrace-2.5.2-cp311-cp311-macosx_11_0_universal2.whl", hash = "sha256:ea2740a3d61876cb07b271af444e98cdc8b730497cfcddbc3794c7a7441b8d15"}, + {file = "ddtrace-2.5.2-cp311-cp311-macosx_11_0_x86_64.whl", hash = "sha256:62e775ba9d2a2b5f952a6609029e965057bdd852ccd6e53b55c0f82ae83aa542"}, + {file = "ddtrace-2.5.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:30186112f156a564efda5e2018240b55baee7664897ca5fc35c452d032a77185"}, + {file = "ddtrace-2.5.2-cp311-cp311-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f9dccdc69de364cffc2b892280724c78cb54db151452a0b6d1b4a89b6f060c44"}, + {file = "ddtrace-2.5.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3aa2543c2303ab325af7794f2a8a420133cd9222e70bfbce3869da146fc5e2ba"}, + {file = "ddtrace-2.5.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:aa2e64f79ada9f2fd5307cd0eba726d8585e47b0282fb9463aaa4b267265e94a"}, + {file = "ddtrace-2.5.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:37b4d55a5be59530e6e5761a36d727aee812be69c81b00ee0182eb62be6f3b75"}, + {file = "ddtrace-2.5.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:6d97f990d2322a23e82203cc5a2aa694fb0d42541a44bb120390e6598a63e5f5"}, + {file = "ddtrace-2.5.2-cp311-cp311-win32.whl", hash = "sha256:5d3f1bc3ce87fbcf2256197178179ef681df720ebbc39b0559bda00247744533"}, + {file = "ddtrace-2.5.2-cp311-cp311-win_amd64.whl", hash = "sha256:a50057085b0972e695bb1ef3042f6cd6a1a3b12111fac4985942f2dbbcf8ac2f"}, + {file = "ddtrace-2.5.2-cp312-cp312-macosx_11_0_universal2.whl", hash = "sha256:b923b099b9a1e50f01ce8bcd4d11e3255a48c71f3e6314dd9a482baed0a87ed6"}, + {file = "ddtrace-2.5.2-cp312-cp312-macosx_11_0_x86_64.whl", hash = "sha256:512d3975b1657c706ca9c84373e5fce323f6fc94bfac33c30876ad8d55e0ea71"}, + {file = "ddtrace-2.5.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4c54bc474c70151d5a141061b6c20a1efabdf458e4239c790d45fa12a13b8e7d"}, + {file = "ddtrace-2.5.2-cp312-cp312-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:b5fb2bbd38dc46ba6a7ea1031c4751b1ca888be5fac8a42049ebc2517707c00d"}, + {file = "ddtrace-2.5.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:caa6fb6bcfb3810d8f0882e489e7d2ef4dd3a92b452cfdd8d1fd4703dc496b17"}, + {file = "ddtrace-2.5.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:3f4eed40d978352c7371804ecb68bbe9e55967bb904bd03b0568554e0b6b92cf"}, + {file = "ddtrace-2.5.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:57606af5380888e2e7cc67b7c4fa5e1bc51d29c48f004b4be0cbe1b319fddc75"}, + {file = "ddtrace-2.5.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:ee8d0259a004964a8eddb394aa84a5754435d4270cd2041e6559c9e68fa49141"}, + {file = "ddtrace-2.5.2-cp312-cp312-win32.whl", hash = "sha256:4df564e620ec7e657fcdb0d5bf1231aa1357bf49b736f0d9e9f6df17a23fc569"}, + {file = "ddtrace-2.5.2-cp312-cp312-win_amd64.whl", hash = "sha256:637f16af1c84566bde044798312c67bc5676df949632ab02e740440558f2a598"}, + {file = "ddtrace-2.5.2-cp37-cp37m-macosx_11_0_x86_64.whl", hash = "sha256:d24841a9390f3e169edcaf1ca5ac80599062e66dee43a510decb25e779b6f7b4"}, + {file = "ddtrace-2.5.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:49aa4e0210862e829e09569de2e2f34ac17c5e246567c5b6662ec21e2a06d938"}, + {file = "ddtrace-2.5.2-cp37-cp37m-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:985738fe875b11f05dfa2b1f21a619d499344eb740f63e01d6eae1fb29eb949b"}, + {file = "ddtrace-2.5.2-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8814321822e4afc95ac86fbc476dc20d78dd4b1d510c02606459df4580093d18"}, + {file = "ddtrace-2.5.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:ad6c0ae7baff9d00c689834aec0627274d681ed1d2a8ae627348a6191e8d32ec"}, + {file = "ddtrace-2.5.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:aa596f2e80c525a2310e605bfa3fa6ba6790b2ae90c02e47ceee0e62ceae17a6"}, + {file = "ddtrace-2.5.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:6bdfae9fa03af334820678196a4895450d0b6bd9f1b5119d42ddbd327a55fcce"}, + {file = "ddtrace-2.5.2-cp37-cp37m-win32.whl", hash = "sha256:227bb0391d310e0d5a54505c7ab59f9692a5db91dc492373489bc45726980e1d"}, + {file = "ddtrace-2.5.2-cp37-cp37m-win_amd64.whl", hash = "sha256:6e55c4738b58b4452933204305243e19000f6f283af93bf51b63382100cb8f21"}, + {file = "ddtrace-2.5.2-cp38-cp38-macosx_11_0_universal2.whl", hash = "sha256:4d9e7a9e26c38ae1e368f5d820e78459ff2d39689f40d4a3db185ddb3686c383"}, + {file = "ddtrace-2.5.2-cp38-cp38-macosx_11_0_x86_64.whl", hash = "sha256:c361ea11b442b04d8e011528205ed65b926d71d18f38d372270204eabf49b068"}, + {file = "ddtrace-2.5.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aafd86eeea622cd0e8cf6b63632efc67a52a32317d2a376382ef6170d383c9f"}, + {file = "ddtrace-2.5.2-cp38-cp38-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3ff039635470ba483ed448baaf6337d85a731b17af62fef06dfa811f761f374f"}, + {file = "ddtrace-2.5.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20f1cb3bea1170410d603f9d557918c24d4d8783659c03817daea6352d9f37f9"}, + {file = "ddtrace-2.5.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7351500241eb24c7d789b371a6860ca2b0e2db1ff9d317089153b562a3a461e1"}, + {file = "ddtrace-2.5.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:a2cfc6ee800890556e404b94d13680c83952efa5d3dafa72ef8cb08a8782f874"}, + {file = "ddtrace-2.5.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:96a791f03b62ebdb9f3e635a0e93711149123a8fc1c1c152be0d1cdb5d8e6359"}, + {file = "ddtrace-2.5.2-cp38-cp38-win32.whl", hash = "sha256:6c61e72abec3f2f6b46e53712a32a971de1b6a9be657d5ebeff1334f6146babc"}, + {file = "ddtrace-2.5.2-cp38-cp38-win_amd64.whl", hash = "sha256:b93d8b536f5fc45a72bb2785051dc729f4d581ef2d69ed10bccae6a7487477b2"}, + {file = "ddtrace-2.5.2-cp39-cp39-macosx_11_0_universal2.whl", hash = "sha256:38cbcb7b4ff1371480b29228d2b8e570e7d7b386a7632b96f9600135ec3eb9db"}, + {file = "ddtrace-2.5.2-cp39-cp39-macosx_11_0_x86_64.whl", hash = "sha256:a270d128c6067f52a76ecbb658fae3f4d3bd4888baa9e6159ff82b6de14c53be"}, + {file = "ddtrace-2.5.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1e59f3958016fcec5eb16abd7979a9ec4d850733e2a03b878b096277fc092784"}, + {file = "ddtrace-2.5.2-cp39-cp39-manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:066403f0e00a8de09c8187037befe7463d1fab5d8178b62a07c2542792710d14"}, + {file = "ddtrace-2.5.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cbbcbf24bca8497f1412ec438fbdc94847aef9e86092ffd4f8626bbe6d278d33"}, + {file = "ddtrace-2.5.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:d34f8da809e2783770a6c88396b3653fb12a4196e9b5f16b8c10f37bbf2b7b31"}, + {file = "ddtrace-2.5.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:9eaca41664dd0c2bd7257fe2e91c7e46718b20591bfaa0b5c01c39b599115f88"}, + {file = "ddtrace-2.5.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:8f4b67e02ba5c316711719dcfc15e94f47684e7af1785289d016a29a2c664827"}, + {file = "ddtrace-2.5.2-cp39-cp39-win32.whl", hash = "sha256:9bbd675d73aae6516e02a86cb830778771dafb0e182d5a122270ccd82ee77eed"}, + {file = "ddtrace-2.5.2-cp39-cp39-win_amd64.whl", hash = "sha256:e93f3f5d3d57beb492b04286c758be65495908bd313df6f56865ad7af222e49e"}, + {file = "ddtrace-2.5.2.tar.gz", hash = "sha256:5addeb19eea5ebdc23c493e5635f4c8737795b48ba637117a1895f31b900985f"}, ] [package.dependencies] @@ -1229,13 +1229,13 @@ testing = ["hatch", "pre-commit", "pytest", "tox"] [[package]] name = "faker" -version = "22.5.1" +version = "22.7.0" description = "Faker is a Python package that generates fake data for you." optional = false python-versions = ">=3.8" files = [ - {file = "Faker-22.5.1-py3-none-any.whl", hash = "sha256:4e7bb19c1955bb978bf1d4cb0cf25930e37de0e7dfbc6abd768fd4784d9a9653"}, - {file = "Faker-22.5.1.tar.gz", hash = "sha256:79cbe3be786789efa05b8c75d7e0ec4efa6ecb786b8fe90eae49c2f8f9cbe31a"}, + {file = "Faker-22.7.0-py3-none-any.whl", hash = "sha256:d12edbac08a82a75ecd588f299f44f12e33f000c15fe414abc417f0836cb51ae"}, + {file = "Faker-22.7.0.tar.gz", hash = "sha256:f797529ebeb9bd9e1851106b99e156c9bebe67d2730c8393a1705ed1c864f1bf"}, ] [package.dependencies] @@ -1269,22 +1269,22 @@ files = [ [[package]] name = "fastapi" -version = "0.109.0" +version = "0.109.2" description = "FastAPI framework, high performance, easy to learn, fast to code, ready for production" optional = false python-versions = ">=3.8" files = [ - {file = "fastapi-0.109.0-py3-none-any.whl", hash = "sha256:8c77515984cd8e8cfeb58364f8cc7a28f0692088475e2614f7bf03275eba9093"}, - {file = "fastapi-0.109.0.tar.gz", hash = "sha256:b978095b9ee01a5cf49b19f4bc1ac9b8ca83aa076e770ef8fd9af09a2b88d191"}, + {file = "fastapi-0.109.2-py3-none-any.whl", hash = "sha256:2c9bab24667293b501cad8dd388c05240c850b58ec5876ee3283c47d6e1e3a4d"}, + {file = "fastapi-0.109.2.tar.gz", hash = "sha256:f3817eac96fe4f65a2ebb4baa000f394e55f5fccdaf7f75250804bc58f354f73"}, ] [package.dependencies] pydantic = ">=1.7.4,<1.8 || >1.8,<1.8.1 || >1.8.1,<2.0.0 || >2.0.0,<2.0.1 || >2.0.1,<2.1.0 || >2.1.0,<3.0.0" -starlette = ">=0.35.0,<0.36.0" +starlette = ">=0.36.3,<0.37.0" typing-extensions = ">=4.8.0" [package.extras] -all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.5)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] +all = ["email-validator (>=2.0.0)", "httpx (>=0.23.0)", "itsdangerous (>=1.1.0)", "jinja2 (>=2.11.2)", "orjson (>=3.2.1)", "pydantic-extra-types (>=2.0.0)", "pydantic-settings (>=2.0.0)", "python-multipart (>=0.0.7)", "pyyaml (>=5.3.1)", "ujson (>=4.0.1,!=4.0.2,!=4.1.0,!=4.2.0,!=4.3.0,!=5.0.0,!=5.1.0)", "uvicorn[standard] (>=0.12.0)"] [[package]] name = "fastjsonschema" @@ -1318,13 +1318,13 @@ typing = ["typing-extensions (>=4.8)"] [[package]] name = "flask" -version = "3.0.1" +version = "3.0.2" description = "A simple framework for building complex web applications." optional = false python-versions = ">=3.8" files = [ - {file = "flask-3.0.1-py3-none-any.whl", hash = "sha256:ca631a507f6dfe6c278ae20112cea3ff54ff2216390bf8880f6b035a5354af13"}, - {file = "flask-3.0.1.tar.gz", hash = "sha256:6489f51bb3666def6f314e15f19d50a1869a19ae0e8c9a3641ffe66c77d42403"}, + {file = "flask-3.0.2-py3-none-any.whl", hash = "sha256:3232e0e9c850d781933cf0207523d1ece087eb8d87b23777ae38456e2fbe7c6e"}, + {file = "flask-3.0.2.tar.gz", hash = "sha256:822c03f4b799204250a7ee84b1eddc40665395333973dfb9deebfe425fefcb7d"}, ] [package.dependencies] @@ -1902,18 +1902,19 @@ dev = ["Sphinx (>=5.1.1)", "black (==23.9.1)", "build (>=0.10.0)", "coverage (>= [[package]] name = "litestar" -version = "2.5.1" +version = "2.5.5" description = "Litestar - A production-ready, highly performant, extensible ASGI API Framework" optional = false python-versions = "<4.0,>=3.8" files = [ - {file = "litestar-2.5.1-py3-none-any.whl", hash = "sha256:6423c8331add1ba52aca5a3769a3c41d3224b176ddd8778fb606f8db60b2e9cb"}, - {file = "litestar-2.5.1.tar.gz", hash = "sha256:6307278ba4f796542b0cdbfeac82a5e71233da20cb7f744d16c8c7723da3a1cd"}, + {file = "litestar-2.5.5-py3-none-any.whl", hash = "sha256:7797e74dd5bb465f6398cf35e5d5bfb99fee92f66b4afd4c066f7dc370510021"}, + {file = "litestar-2.5.5.tar.gz", hash = "sha256:0ae9e526ec89c869883e3e5818f71fb2ae3d53490e0f316ccd71d5cbe5ce0c49"}, ] [package.dependencies] anyio = ">=3" click = "*" +exceptiongroup = {version = "*", markers = "python_version < \"3.11\""} httpx = ">=0.22" importlib-metadata = {version = "*", markers = "python_version < \"3.10\""} importlib-resources = {version = ">=5.12.0", markers = "python_version < \"3.9\""} @@ -1948,13 +1949,13 @@ structlog = ["structlog"] [[package]] name = "mako" -version = "1.3.1" +version = "1.3.2" description = "A super-fast templating language that borrows the best ideas from the existing templating languages." optional = false python-versions = ">=3.8" files = [ - {file = "Mako-1.3.1-py3-none-any.whl", hash = "sha256:463f03e04559689adaee25e0967778d6ad41285ed607dc1e7df0dd4e4df81f9e"}, - {file = "Mako-1.3.1.tar.gz", hash = "sha256:baee30b9c61718e093130298e678abed0dbfa1b411fcc4c1ab4df87cd631a0f2"}, + {file = "Mako-1.3.2-py3-none-any.whl", hash = "sha256:32a99d70754dfce237019d17ffe4a282d2d3351b9c476e90d8a60e63f133b80c"}, + {file = "Mako-1.3.2.tar.gz", hash = "sha256:2a0c8ad7f6274271b3bb7467dd37cf9cc6dab4bc19cb69a4ef10669402de698e"}, ] [package.dependencies] @@ -2016,6 +2017,16 @@ files = [ {file = "MarkupSafe-2.1.3-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:5bbe06f8eeafd38e5d0a4894ffec89378b6c6a625ff57e3028921f8ff59318ac"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win32.whl", hash = "sha256:dd15ff04ffd7e05ffcb7fe79f1b98041b8ea30ae9234aed2a9168b5797c3effb"}, {file = "MarkupSafe-2.1.3-cp311-cp311-win_amd64.whl", hash = "sha256:134da1eca9ec0ae528110ccc9e48041e0828d79f24121a1a146161103c76e686"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:f698de3fd0c4e6972b92290a45bd9b1536bffe8c6759c62471efaa8acb4c37bc"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:aa57bd9cf8ae831a362185ee444e15a93ecb2e344c8e52e4d721ea3ab6ef1823"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ffcc3f7c66b5f5b7931a5aa68fc9cecc51e685ef90282f4a82f0f5e9b704ad11"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:47d4f1c5f80fc62fdd7777d0d40a2e9dda0a05883ab11374334f6c4de38adffd"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1f67c7038d560d92149c060157d623c542173016c4babc0c1913cca0564b9939"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9aad3c1755095ce347e26488214ef77e0485a3c34a50c5a5e2471dff60b9dd9c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:14ff806850827afd6b07a5f32bd917fb7f45b046ba40c57abdb636674a8b559c"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:8f9293864fe09b8149f0cc42ce56e3f0e54de883a9de90cd427f191c346eb2e1"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win32.whl", hash = "sha256:715d3562f79d540f251b99ebd6d8baa547118974341db04f5ad06d5ea3eb8007"}, + {file = "MarkupSafe-2.1.3-cp312-cp312-win_amd64.whl", hash = "sha256:1b8dd8c3fd14349433c79fa8abeb573a55fc0fdd769133baac1f5e07abf54aeb"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:8e254ae696c88d98da6555f5ace2279cf7cd5b3f52be2b5cf97feafe883b58d2"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cb0932dc158471523c9637e807d9bfb93e06a95cbf010f1a38b98623b929ef2b"}, {file = "MarkupSafe-2.1.3-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:9402b03f1a1b4dc4c19845e5c749e3ab82d5078d16a2a4c2cd2df62d57bb0707"}, @@ -2189,85 +2200,101 @@ yaml = ["pyyaml"] [[package]] name = "multidict" -version = "6.0.4" +version = "6.0.5" description = "multidict implementation" optional = false python-versions = ">=3.7" files = [ - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:0b1a97283e0c85772d613878028fec909f003993e1007eafa715b24b377cb9b8"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:eeb6dcc05e911516ae3d1f207d4b0520d07f54484c49dfc294d6e7d63b734171"}, - {file = "multidict-6.0.4-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:d6d635d5209b82a3492508cf5b365f3446afb65ae7ebd755e70e18f287b0adf7"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:c048099e4c9e9d615545e2001d3d8a4380bd403e1a0578734e0d31703d1b0c0b"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ea20853c6dbbb53ed34cb4d080382169b6f4554d394015f1bef35e881bf83547"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:16d232d4e5396c2efbbf4f6d4df89bfa905eb0d4dc5b3549d872ab898451f569"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:36c63aaa167f6c6b04ef2c85704e93af16c11d20de1d133e39de6a0e84582a93"}, - {file = "multidict-6.0.4-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:64bdf1086b6043bf519869678f5f2757f473dee970d7abf6da91ec00acb9cb98"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:43644e38f42e3af682690876cff722d301ac585c5b9e1eacc013b7a3f7b696a0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:7582a1d1030e15422262de9f58711774e02fa80df0d1578995c76214f6954988"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:ddff9c4e225a63a5afab9dd15590432c22e8057e1a9a13d28ed128ecf047bbdc"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:ee2a1ece51b9b9e7752e742cfb661d2a29e7bcdba2d27e66e28a99f1890e4fa0"}, - {file = "multidict-6.0.4-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:a2e4369eb3d47d2034032a26c7a80fcb21a2cb22e1173d761a162f11e562caa5"}, - {file = "multidict-6.0.4-cp310-cp310-win32.whl", hash = "sha256:574b7eae1ab267e5f8285f0fe881f17efe4b98c39a40858247720935b893bba8"}, - {file = "multidict-6.0.4-cp310-cp310-win_amd64.whl", hash = "sha256:4dcbb0906e38440fa3e325df2359ac6cb043df8e58c965bb45f4e406ecb162cc"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:0dfad7a5a1e39c53ed00d2dd0c2e36aed4650936dc18fd9a1826a5ae1cad6f03"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:64da238a09d6039e3bd39bb3aee9c21a5e34f28bfa5aa22518581f910ff94af3"}, - {file = "multidict-6.0.4-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ff959bee35038c4624250473988b24f846cbeb2c6639de3602c073f10410ceba"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:01a3a55bd90018c9c080fbb0b9f4891db37d148a0a18722b42f94694f8b6d4c9"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:c5cb09abb18c1ea940fb99360ea0396f34d46566f157122c92dfa069d3e0e982"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:666daae833559deb2d609afa4490b85830ab0dfca811a98b70a205621a6109fe"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:11bdf3f5e1518b24530b8241529d2050014c884cf18b6fc69c0c2b30ca248710"}, - {file = "multidict-6.0.4-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:7d18748f2d30f94f498e852c67d61261c643b349b9d2a581131725595c45ec6c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:458f37be2d9e4c95e2d8866a851663cbc76e865b78395090786f6cd9b3bbf4f4"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:b1a2eeedcead3a41694130495593a559a668f382eee0727352b9a41e1c45759a"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:7d6ae9d593ef8641544d6263c7fa6408cc90370c8cb2bbb65f8d43e5b0351d9c"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:5979b5632c3e3534e42ca6ff856bb24b2e3071b37861c2c727ce220d80eee9ed"}, - {file = "multidict-6.0.4-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:dcfe792765fab89c365123c81046ad4103fcabbc4f56d1c1997e6715e8015461"}, - {file = "multidict-6.0.4-cp311-cp311-win32.whl", hash = "sha256:3601a3cece3819534b11d4efc1eb76047488fddd0c85a3948099d5da4d504636"}, - {file = "multidict-6.0.4-cp311-cp311-win_amd64.whl", hash = "sha256:81a4f0b34bd92df3da93315c6a59034df95866014ac08535fc819f043bfd51f0"}, - {file = "multidict-6.0.4-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:67040058f37a2a51ed8ea8f6b0e6ee5bd78ca67f169ce6122f3e2ec80dfe9b78"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:853888594621e6604c978ce2a0444a1e6e70c8d253ab65ba11657659dcc9100f"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:39ff62e7d0f26c248b15e364517a72932a611a9b75f35b45be078d81bdb86603"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:af048912e045a2dc732847d33821a9d84ba553f5c5f028adbd364dd4765092ac"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b1e8b901e607795ec06c9e42530788c45ac21ef3aaa11dbd0c69de543bfb79a9"}, - {file = "multidict-6.0.4-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:62501642008a8b9871ddfccbf83e4222cf8ac0d5aeedf73da36153ef2ec222d2"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:99b76c052e9f1bc0721f7541e5e8c05db3941eb9ebe7b8553c625ef88d6eefde"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:509eac6cf09c794aa27bcacfd4d62c885cce62bef7b2c3e8b2e49d365b5003fe"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:21a12c4eb6ddc9952c415f24eef97e3e55ba3af61f67c7bc388dcdec1404a067"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:5cad9430ab3e2e4fa4a2ef4450f548768400a2ac635841bc2a56a2052cdbeb87"}, - {file = "multidict-6.0.4-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:ab55edc2e84460694295f401215f4a58597f8f7c9466faec545093045476327d"}, - {file = "multidict-6.0.4-cp37-cp37m-win32.whl", hash = "sha256:5a4dcf02b908c3b8b17a45fb0f15b695bf117a67b76b7ad18b73cf8e92608775"}, - {file = "multidict-6.0.4-cp37-cp37m-win_amd64.whl", hash = "sha256:6ed5f161328b7df384d71b07317f4d8656434e34591f20552c7bcef27b0ab88e"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:5fc1b16f586f049820c5c5b17bb4ee7583092fa0d1c4e28b5239181ff9532e0c"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:1502e24330eb681bdaa3eb70d6358e818e8e8f908a22a1851dfd4e15bc2f8161"}, - {file = "multidict-6.0.4-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:b692f419760c0e65d060959df05f2a531945af31fda0c8a3b3195d4efd06de11"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:45e1ecb0379bfaab5eef059f50115b54571acfbe422a14f668fc8c27ba410e7e"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ddd3915998d93fbcd2566ddf9cf62cdb35c9e093075f862935573d265cf8f65d"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:59d43b61c59d82f2effb39a93c48b845efe23a3852d201ed2d24ba830d0b4cf2"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:cc8e1d0c705233c5dd0c5e6460fbad7827d5d36f310a0fadfd45cc3029762258"}, - {file = "multidict-6.0.4-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:d6aa0418fcc838522256761b3415822626f866758ee0bc6632c9486b179d0b52"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:6748717bb10339c4760c1e63da040f5f29f5ed6e59d76daee30305894069a660"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:4d1a3d7ef5e96b1c9e92f973e43aa5e5b96c659c9bc3124acbbd81b0b9c8a951"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:4372381634485bec7e46718edc71528024fcdc6f835baefe517b34a33c731d60"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:fc35cb4676846ef752816d5be2193a1e8367b4c1397b74a565a9d0389c433a1d"}, - {file = "multidict-6.0.4-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:4b9d9e4e2b37daddb5c23ea33a3417901fa7c7b3dee2d855f63ee67a0b21e5b1"}, - {file = "multidict-6.0.4-cp38-cp38-win32.whl", hash = "sha256:e41b7e2b59679edfa309e8db64fdf22399eec4b0b24694e1b2104fb789207779"}, - {file = "multidict-6.0.4-cp38-cp38-win_amd64.whl", hash = "sha256:d6c254ba6e45d8e72739281ebc46ea5eb5f101234f3ce171f0e9f5cc86991480"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:16ab77bbeb596e14212e7bab8429f24c1579234a3a462105cda4a66904998664"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:bc779e9e6f7fda81b3f9aa58e3a6091d49ad528b11ed19f6621408806204ad35"}, - {file = "multidict-6.0.4-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:4ceef517eca3e03c1cceb22030a3e39cb399ac86bff4e426d4fc6ae49052cc60"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:281af09f488903fde97923c7744bb001a9b23b039a909460d0f14edc7bf59706"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:52f2dffc8acaba9a2f27174c41c9e57f60b907bb9f096b36b1a1f3be71c6284d"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b41156839806aecb3641f3208c0dafd3ac7775b9c4c422d82ee2a45c34ba81ca"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d5e3fc56f88cc98ef8139255cf8cd63eb2c586531e43310ff859d6bb3a6b51f1"}, - {file = "multidict-6.0.4-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:8316a77808c501004802f9beebde51c9f857054a0c871bd6da8280e718444449"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:f70b98cd94886b49d91170ef23ec5c0e8ebb6f242d734ed7ed677b24d50c82cf"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:bf6774e60d67a9efe02b3616fee22441d86fab4c6d335f9d2051d19d90a40063"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:e69924bfcdda39b722ef4d9aa762b2dd38e4632b3641b1d9a57ca9cd18f2f83a"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:6b181d8c23da913d4ff585afd1155a0e1194c0b50c54fcfe286f70cdaf2b7176"}, - {file = "multidict-6.0.4-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:52509b5be062d9eafc8170e53026fbc54cf3b32759a23d07fd935fb04fc22d95"}, - {file = "multidict-6.0.4-cp39-cp39-win32.whl", hash = "sha256:27c523fbfbdfd19c6867af7346332b62b586eed663887392cff78d614f9ec313"}, - {file = "multidict-6.0.4-cp39-cp39-win_amd64.whl", hash = "sha256:33029f5734336aa0d4c0384525da0387ef89148dc7191aae00ca5fb23d7aafc2"}, - {file = "multidict-6.0.4.tar.gz", hash = "sha256:3666906492efb76453c0e7b97f2cf459b0682e7402c0489a95484965dbc1da49"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:228b644ae063c10e7f324ab1ab6b548bdf6f8b47f3ec234fef1093bc2735e5f9"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:896ebdcf62683551312c30e20614305f53125750803b614e9e6ce74a96232604"}, + {file = "multidict-6.0.5-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:411bf8515f3be9813d06004cac41ccf7d1cd46dfe233705933dd163b60e37600"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1d147090048129ce3c453f0292e7697d333db95e52616b3793922945804a433c"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:215ed703caf15f578dca76ee6f6b21b7603791ae090fbf1ef9d865571039ade5"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7c6390cf87ff6234643428991b7359b5f59cc15155695deb4eda5c777d2b880f"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:21fd81c4ebdb4f214161be351eb5bcf385426bf023041da2fd9e60681f3cebae"}, + {file = "multidict-6.0.5-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:3cc2ad10255f903656017363cd59436f2111443a76f996584d1077e43ee51182"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:6939c95381e003f54cd4c5516740faba40cf5ad3eeff460c3ad1d3e0ea2549bf"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:220dd781e3f7af2c2c1053da9fa96d9cf3072ca58f057f4c5adaaa1cab8fc442"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_ppc64le.whl", hash = "sha256:766c8f7511df26d9f11cd3a8be623e59cca73d44643abab3f8c8c07620524e4a"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_s390x.whl", hash = "sha256:fe5d7785250541f7f5019ab9cba2c71169dc7d74d0f45253f8313f436458a4ef"}, + {file = "multidict-6.0.5-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:c1c1496e73051918fcd4f58ff2e0f2f3066d1c76a0c6aeffd9b45d53243702cc"}, + {file = "multidict-6.0.5-cp310-cp310-win32.whl", hash = "sha256:7afcdd1fc07befad18ec4523a782cde4e93e0a2bf71239894b8d61ee578c1319"}, + {file = "multidict-6.0.5-cp310-cp310-win_amd64.whl", hash = "sha256:99f60d34c048c5c2fabc766108c103612344c46e35d4ed9ae0673d33c8fb26e8"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:f285e862d2f153a70586579c15c44656f888806ed0e5b56b64489afe4a2dbfba"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:53689bb4e102200a4fafa9de9c7c3c212ab40a7ab2c8e474491914d2305f187e"}, + {file = "multidict-6.0.5-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:612d1156111ae11d14afaf3a0669ebf6c170dbb735e510a7438ffe2369a847fd"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7be7047bd08accdb7487737631d25735c9a04327911de89ff1b26b81745bd4e3"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:de170c7b4fe6859beb8926e84f7d7d6c693dfe8e27372ce3b76f01c46e489fcf"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:04bde7a7b3de05732a4eb39c94574db1ec99abb56162d6c520ad26f83267de29"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:85f67aed7bb647f93e7520633d8f51d3cbc6ab96957c71272b286b2f30dc70ed"}, + {file = "multidict-6.0.5-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:425bf820055005bfc8aa9a0b99ccb52cc2f4070153e34b701acc98d201693733"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:d3eb1ceec286eba8220c26f3b0096cf189aea7057b6e7b7a2e60ed36b373b77f"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:7901c05ead4b3fb75113fb1dd33eb1253c6d3ee37ce93305acd9d38e0b5f21a4"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_ppc64le.whl", hash = "sha256:e0e79d91e71b9867c73323a3444724d496c037e578a0e1755ae159ba14f4f3d1"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_s390x.whl", hash = "sha256:29bfeb0dff5cb5fdab2023a7a9947b3b4af63e9c47cae2a10ad58394b517fddc"}, + {file = "multidict-6.0.5-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:e030047e85cbcedbfc073f71836d62dd5dadfbe7531cae27789ff66bc551bd5e"}, + {file = "multidict-6.0.5-cp311-cp311-win32.whl", hash = "sha256:2f4848aa3baa109e6ab81fe2006c77ed4d3cd1e0ac2c1fbddb7b1277c168788c"}, + {file = "multidict-6.0.5-cp311-cp311-win_amd64.whl", hash = "sha256:2faa5ae9376faba05f630d7e5e6be05be22913782b927b19d12b8145968a85ea"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:51d035609b86722963404f711db441cf7134f1889107fb171a970c9701f92e1e"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:cbebcd5bcaf1eaf302617c114aa67569dd3f090dd0ce8ba9e35e9985b41ac35b"}, + {file = "multidict-6.0.5-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:2ffc42c922dbfddb4a4c3b438eb056828719f07608af27d163191cb3e3aa6cc5"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:ceb3b7e6a0135e092de86110c5a74e46bda4bd4fbfeeb3a3bcec79c0f861e450"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:79660376075cfd4b2c80f295528aa6beb2058fd289f4c9252f986751a4cd0496"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:e4428b29611e989719874670fd152b6625500ad6c686d464e99f5aaeeaca175a"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d84a5c3a5f7ce6db1f999fb9438f686bc2e09d38143f2d93d8406ed2dd6b9226"}, + {file = "multidict-6.0.5-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:76c0de87358b192de7ea9649beb392f107dcad9ad27276324c24c91774ca5271"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:79a6d2ba910adb2cbafc95dad936f8b9386e77c84c35bc0add315b856d7c3abb"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:92d16a3e275e38293623ebf639c471d3e03bb20b8ebb845237e0d3664914caef"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_ppc64le.whl", hash = "sha256:fb616be3538599e797a2017cccca78e354c767165e8858ab5116813146041a24"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_s390x.whl", hash = "sha256:14c2976aa9038c2629efa2c148022ed5eb4cb939e15ec7aace7ca932f48f9ba6"}, + {file = "multidict-6.0.5-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:435a0984199d81ca178b9ae2c26ec3d49692d20ee29bc4c11a2a8d4514c67eda"}, + {file = "multidict-6.0.5-cp312-cp312-win32.whl", hash = "sha256:9fe7b0653ba3d9d65cbe7698cca585bf0f8c83dbbcc710db9c90f478e175f2d5"}, + {file = "multidict-6.0.5-cp312-cp312-win_amd64.whl", hash = "sha256:01265f5e40f5a17f8241d52656ed27192be03bfa8764d88e8220141d1e4b3556"}, + {file = "multidict-6.0.5-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:19fe01cea168585ba0f678cad6f58133db2aa14eccaf22f88e4a6dccadfad8b3"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6bf7a982604375a8d49b6cc1b781c1747f243d91b81035a9b43a2126c04766f5"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:107c0cdefe028703fb5dafe640a409cb146d44a6ae201e55b35a4af8e95457dd"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:403c0911cd5d5791605808b942c88a8155c2592e05332d2bf78f18697a5fa15e"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aeaf541ddbad8311a87dd695ed9642401131ea39ad7bc8cf3ef3967fd093b626"}, + {file = "multidict-6.0.5-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:e4972624066095e52b569e02b5ca97dbd7a7ddd4294bf4e7247d52635630dd83"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:d946b0a9eb8aaa590df1fe082cee553ceab173e6cb5b03239716338629c50c7a"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:b55358304d7a73d7bdf5de62494aaf70bd33015831ffd98bc498b433dfe5b10c"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_ppc64le.whl", hash = "sha256:a3145cb08d8625b2d3fee1b2d596a8766352979c9bffe5d7833e0503d0f0b5e5"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_s390x.whl", hash = "sha256:d65f25da8e248202bd47445cec78e0025c0fe7582b23ec69c3b27a640dd7a8e3"}, + {file = "multidict-6.0.5-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:c9bf56195c6bbd293340ea82eafd0071cb3d450c703d2c93afb89f93b8386ccc"}, + {file = "multidict-6.0.5-cp37-cp37m-win32.whl", hash = "sha256:69db76c09796b313331bb7048229e3bee7928eb62bab5e071e9f7fcc4879caee"}, + {file = "multidict-6.0.5-cp37-cp37m-win_amd64.whl", hash = "sha256:fce28b3c8a81b6b36dfac9feb1de115bab619b3c13905b419ec71d03a3fc1423"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:76f067f5121dcecf0d63a67f29080b26c43c71a98b10c701b0677e4a065fbd54"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:b82cc8ace10ab5bd93235dfaab2021c70637005e1ac787031f4d1da63d493c1d"}, + {file = "multidict-6.0.5-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:5cb241881eefd96b46f89b1a056187ea8e9ba14ab88ba632e68d7a2ecb7aadf7"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e8e94e6912639a02ce173341ff62cc1201232ab86b8a8fcc05572741a5dc7d93"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:09a892e4a9fb47331da06948690ae38eaa2426de97b4ccbfafbdcbe5c8f37ff8"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:55205d03e8a598cfc688c71ca8ea5f66447164efff8869517f175ea632c7cb7b"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:37b15024f864916b4951adb95d3a80c9431299080341ab9544ed148091b53f50"}, + {file = "multidict-6.0.5-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:f2a1dee728b52b33eebff5072817176c172050d44d67befd681609b4746e1c2e"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:edd08e6f2f1a390bf137080507e44ccc086353c8e98c657e666c017718561b89"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:60d698e8179a42ec85172d12f50b1668254628425a6bd611aba022257cac1386"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_ppc64le.whl", hash = "sha256:3d25f19500588cbc47dc19081d78131c32637c25804df8414463ec908631e453"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_s390x.whl", hash = "sha256:4cc0ef8b962ac7a5e62b9e826bd0cd5040e7d401bc45a6835910ed699037a461"}, + {file = "multidict-6.0.5-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:eca2e9d0cc5a889850e9bbd68e98314ada174ff6ccd1129500103df7a94a7a44"}, + {file = "multidict-6.0.5-cp38-cp38-win32.whl", hash = "sha256:4a6a4f196f08c58c59e0b8ef8ec441d12aee4125a7d4f4fef000ccb22f8d7241"}, + {file = "multidict-6.0.5-cp38-cp38-win_amd64.whl", hash = "sha256:0275e35209c27a3f7951e1ce7aaf93ce0d163b28948444bec61dd7badc6d3f8c"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:e7be68734bd8c9a513f2b0cfd508802d6609da068f40dc57d4e3494cefc92929"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:1d9ea7a7e779d7a3561aade7d596649fbecfa5c08a7674b11b423783217933f9"}, + {file = "multidict-6.0.5-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:ea1456df2a27c73ce51120fa2f519f1bea2f4a03a917f4a43c8707cf4cbbae1a"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:cf590b134eb70629e350691ecca88eac3e3b8b3c86992042fb82e3cb1830d5e1"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:5c0631926c4f58e9a5ccce555ad7747d9a9f8b10619621f22f9635f069f6233e"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:dce1c6912ab9ff5f179eaf6efe7365c1f425ed690b03341911bf4939ef2f3046"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c0868d64af83169e4d4152ec612637a543f7a336e4a307b119e98042e852ad9c"}, + {file = "multidict-6.0.5-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:141b43360bfd3bdd75f15ed811850763555a251e38b2405967f8e25fb43f7d40"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:7df704ca8cf4a073334e0427ae2345323613e4df18cc224f647f251e5e75a527"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6214c5a5571802c33f80e6c84713b2c79e024995b9c5897f794b43e714daeec9"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_ppc64le.whl", hash = "sha256:cd6c8fca38178e12c00418de737aef1261576bd1b6e8c6134d3e729a4e858b38"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_s390x.whl", hash = "sha256:e02021f87a5b6932fa6ce916ca004c4d441509d33bbdbeca70d05dff5e9d2479"}, + {file = "multidict-6.0.5-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:ebd8d160f91a764652d3e51ce0d2956b38efe37c9231cd82cfc0bed2e40b581c"}, + {file = "multidict-6.0.5-cp39-cp39-win32.whl", hash = "sha256:04da1bb8c8dbadf2a18a452639771951c662c5ad03aefe4884775454be322c9b"}, + {file = "multidict-6.0.5-cp39-cp39-win_amd64.whl", hash = "sha256:d6f6d4f185481c9669b9447bf9d9cf3b95a0e9df9d169bbc17e363b7d5487755"}, + {file = "multidict-6.0.5-py3-none-any.whl", hash = "sha256:0d63c74e3d7ab26de115c49bffc92cc77ed23395303d496eae515d4204a625e7"}, + {file = "multidict-6.0.5.tar.gz", hash = "sha256:f7e301075edaf50500f0b341543c41194d8df3ae5caf4702f2095f3ca73dd8da"}, ] [[package]] @@ -2473,13 +2500,13 @@ test = ["appdirs (==1.4.4)", "covdefaults (>=2.3)", "pytest (>=7.4)", "pytest-co [[package]] name = "pluggy" -version = "1.3.0" +version = "1.4.0" description = "plugin and hook calling mechanisms for python" optional = false python-versions = ">=3.8" files = [ - {file = "pluggy-1.3.0-py3-none-any.whl", hash = "sha256:d89c696a773f8bd377d18e5ecda92b7a3793cbe66c87060a6fb58c7b6e1061f7"}, - {file = "pluggy-1.3.0.tar.gz", hash = "sha256:cf61ae8f126ac6f7c451172cf30e3e43d3ca77615509771b3a984a0730651e12"}, + {file = "pluggy-1.4.0-py3-none-any.whl", hash = "sha256:7db9f7b503d67d1c5b95f59773ebb58a8c1c288129a88665838012cfb07b8981"}, + {file = "pluggy-1.4.0.tar.gz", hash = "sha256:8c85c2876142a764e5b7548e7d9a0e0ddb46f5185161049a79b7e974454223be"}, ] [package.extras] @@ -2681,18 +2708,18 @@ files = [ [[package]] name = "pydantic" -version = "2.5.3" +version = "2.6.1" description = "Data validation using Python type hints" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic-2.5.3-py3-none-any.whl", hash = "sha256:d0caf5954bee831b6bfe7e338c32b9e30c85dfe080c843680783ac2b631673b4"}, - {file = "pydantic-2.5.3.tar.gz", hash = "sha256:b3ef57c62535b0941697cce638c08900d87fcb67e29cfa99e8a68f747f393f7a"}, + {file = "pydantic-2.6.1-py3-none-any.whl", hash = "sha256:0b6a909df3192245cb736509a92ff69e4fef76116feffec68e93a567347bae6f"}, + {file = "pydantic-2.6.1.tar.gz", hash = "sha256:4fd5c182a2488dc63e6d32737ff19937888001e2a6d86e94b3f233104a5d1fa9"}, ] [package.dependencies] annotated-types = ">=0.4.0" -pydantic-core = "2.14.6" +pydantic-core = "2.16.2" typing-extensions = ">=4.6.1" [package.extras] @@ -2700,116 +2727,90 @@ email = ["email-validator (>=2.0.0)"] [[package]] name = "pydantic-core" -version = "2.14.6" +version = "2.16.2" description = "" optional = false -python-versions = ">=3.7" +python-versions = ">=3.8" files = [ - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_10_7_x86_64.whl", hash = "sha256:72f9a942d739f09cd42fffe5dc759928217649f070056f03c70df14f5770acf9"}, - {file = "pydantic_core-2.14.6-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:6a31d98c0d69776c2576dda4b77b8e0c69ad08e8b539c25c7d0ca0dc19a50d6c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:5aa90562bc079c6c290f0512b21768967f9968e4cfea84ea4ff5af5d917016e4"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:370ffecb5316ed23b667d99ce4debe53ea664b99cc37bfa2af47bc769056d534"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:f85f3843bdb1fe80e8c206fe6eed7a1caeae897e496542cee499c374a85c6e08"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:9862bf828112e19685b76ca499b379338fd4c5c269d897e218b2ae8fcb80139d"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:036137b5ad0cb0004c75b579445a1efccd072387a36c7f217bb8efd1afbe5245"}, - {file = "pydantic_core-2.14.6-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:92879bce89f91f4b2416eba4429c7b5ca22c45ef4a499c39f0c5c69257522c7c"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:0c08de15d50fa190d577e8591f0329a643eeaed696d7771760295998aca6bc66"}, - {file = "pydantic_core-2.14.6-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:36099c69f6b14fc2c49d7996cbf4f87ec4f0e66d1c74aa05228583225a07b590"}, - {file = "pydantic_core-2.14.6-cp310-none-win32.whl", hash = "sha256:7be719e4d2ae6c314f72844ba9d69e38dff342bc360379f7c8537c48e23034b7"}, - {file = "pydantic_core-2.14.6-cp310-none-win_amd64.whl", hash = "sha256:36fa402dcdc8ea7f1b0ddcf0df4254cc6b2e08f8cd80e7010d4c4ae6e86b2a87"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_10_7_x86_64.whl", hash = "sha256:dea7fcd62915fb150cdc373212141a30037e11b761fbced340e9db3379b892d4"}, - {file = "pydantic_core-2.14.6-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ffff855100bc066ff2cd3aa4a60bc9534661816b110f0243e59503ec2df38421"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:1b027c86c66b8627eb90e57aee1f526df77dc6d8b354ec498be9a757d513b92b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:00b1087dabcee0b0ffd104f9f53d7d3eaddfaa314cdd6726143af6bc713aa27e"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:75ec284328b60a4e91010c1acade0c30584f28a1f345bc8f72fe8b9e46ec6a96"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:7e1f4744eea1501404b20b0ac059ff7e3f96a97d3e3f48ce27a139e053bb370b"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:b2602177668f89b38b9f84b7b3435d0a72511ddef45dc14446811759b82235a1"}, - {file = "pydantic_core-2.14.6-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6c8edaea3089bf908dd27da8f5d9e395c5b4dc092dbcce9b65e7156099b4b937"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:478e9e7b360dfec451daafe286998d4a1eeaecf6d69c427b834ae771cad4b622"}, - {file = "pydantic_core-2.14.6-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:b6ca36c12a5120bad343eef193cc0122928c5c7466121da7c20f41160ba00ba2"}, - {file = "pydantic_core-2.14.6-cp311-none-win32.whl", hash = "sha256:2b8719037e570639e6b665a4050add43134d80b687288ba3ade18b22bbb29dd2"}, - {file = "pydantic_core-2.14.6-cp311-none-win_amd64.whl", hash = "sha256:78ee52ecc088c61cce32b2d30a826f929e1708f7b9247dc3b921aec367dc1b23"}, - {file = "pydantic_core-2.14.6-cp311-none-win_arm64.whl", hash = "sha256:a19b794f8fe6569472ff77602437ec4430f9b2b9ec7a1105cfd2232f9ba355e6"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_10_7_x86_64.whl", hash = "sha256:667aa2eac9cd0700af1ddb38b7b1ef246d8cf94c85637cbb03d7757ca4c3fdec"}, - {file = "pydantic_core-2.14.6-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:cdee837710ef6b56ebd20245b83799fce40b265b3b406e51e8ccc5b85b9099b7"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2c5bcf3414367e29f83fd66f7de64509a8fd2368b1edf4351e862910727d3e51"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:26a92ae76f75d1915806b77cf459811e772d8f71fd1e4339c99750f0e7f6324f"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:a983cca5ed1dd9a35e9e42ebf9f278d344603bfcb174ff99a5815f953925140a"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cb92f9061657287eded380d7dc455bbf115430b3aa4741bdc662d02977e7d0af"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ace1e220b078c8e48e82c081e35002038657e4b37d403ce940fa679e57113b"}, - {file = "pydantic_core-2.14.6-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:ef633add81832f4b56d3b4c9408b43d530dfca29e68fb1b797dcb861a2c734cd"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7e90d6cc4aad2cc1f5e16ed56e46cebf4877c62403a311af20459c15da76fd91"}, - {file = "pydantic_core-2.14.6-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e8a5ac97ea521d7bde7621d86c30e86b798cdecd985723c4ed737a2aa9e77d0c"}, - {file = "pydantic_core-2.14.6-cp312-none-win32.whl", hash = "sha256:f27207e8ca3e5e021e2402ba942e5b4c629718e665c81b8b306f3c8b1ddbb786"}, - {file = "pydantic_core-2.14.6-cp312-none-win_amd64.whl", hash = "sha256:b3e5fe4538001bb82e2295b8d2a39356a84694c97cb73a566dc36328b9f83b40"}, - {file = "pydantic_core-2.14.6-cp312-none-win_arm64.whl", hash = "sha256:64634ccf9d671c6be242a664a33c4acf12882670b09b3f163cd00a24cffbd74e"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_10_7_x86_64.whl", hash = "sha256:24368e31be2c88bd69340fbfe741b405302993242ccb476c5c3ff48aeee1afe0"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-macosx_11_0_arm64.whl", hash = "sha256:e33b0834f1cf779aa839975f9d8755a7c2420510c0fa1e9fa0497de77cd35d2c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6af4b3f52cc65f8a0bc8b1cd9676f8c21ef3e9132f21fed250f6958bd7223bed"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:d15687d7d7f40333bd8266f3814c591c2e2cd263fa2116e314f60d82086e353a"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:095b707bb287bfd534044166ab767bec70a9bba3175dcdc3371782175c14e43c"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:94fc0e6621e07d1e91c44e016cc0b189b48db053061cc22d6298a611de8071bb"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1ce830e480f6774608dedfd4a90c42aac4a7af0a711f1b52f807130c2e434c06"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a306cdd2ad3a7d795d8e617a58c3a2ed0f76c8496fb7621b6cd514eb1532cae8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2f5fa187bde8524b1e37ba894db13aadd64faa884657473b03a019f625cee9a8"}, - {file = "pydantic_core-2.14.6-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:438027a975cc213a47c5d70672e0d29776082155cfae540c4e225716586be75e"}, - {file = "pydantic_core-2.14.6-cp37-none-win32.whl", hash = "sha256:f96ae96a060a8072ceff4cfde89d261837b4294a4f28b84a28765470d502ccc6"}, - {file = "pydantic_core-2.14.6-cp37-none-win_amd64.whl", hash = "sha256:e646c0e282e960345314f42f2cea5e0b5f56938c093541ea6dbf11aec2862391"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_10_7_x86_64.whl", hash = "sha256:db453f2da3f59a348f514cfbfeb042393b68720787bbef2b4c6068ea362c8149"}, - {file = "pydantic_core-2.14.6-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:3860c62057acd95cc84044e758e47b18dcd8871a328ebc8ccdefd18b0d26a21b"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:36026d8f99c58d7044413e1b819a67ca0e0b8ebe0f25e775e6c3d1fabb3c38fb"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8ed1af8692bd8d2a29d702f1a2e6065416d76897d726e45a1775b1444f5928a7"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:314ccc4264ce7d854941231cf71b592e30d8d368a71e50197c905874feacc8a8"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:982487f8931067a32e72d40ab6b47b1628a9c5d344be7f1a4e668fb462d2da42"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:2dbe357bc4ddda078f79d2a36fc1dd0494a7f2fad83a0a684465b6f24b46fe80"}, - {file = "pydantic_core-2.14.6-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:2f6ffc6701a0eb28648c845f4945a194dc7ab3c651f535b81793251e1185ac3d"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:7f5025db12fc6de7bc1104d826d5aee1d172f9ba6ca936bf6474c2148ac336c1"}, - {file = "pydantic_core-2.14.6-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:dab03ed811ed1c71d700ed08bde8431cf429bbe59e423394f0f4055f1ca0ea60"}, - {file = "pydantic_core-2.14.6-cp38-none-win32.whl", hash = "sha256:dfcbebdb3c4b6f739a91769aea5ed615023f3c88cb70df812849aef634c25fbe"}, - {file = "pydantic_core-2.14.6-cp38-none-win_amd64.whl", hash = "sha256:99b14dbea2fdb563d8b5a57c9badfcd72083f6006caf8e126b491519c7d64ca8"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_10_7_x86_64.whl", hash = "sha256:4ce8299b481bcb68e5c82002b96e411796b844d72b3e92a3fbedfe8e19813eab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b9a9d92f10772d2a181b5ca339dee066ab7d1c9a34ae2421b2a52556e719756f"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:fd9e98b408384989ea4ab60206b8e100d8687da18b5c813c11e92fd8212a98e0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:4f86f1f318e56f5cbb282fe61eb84767aee743ebe32c7c0834690ebea50c0a6b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:86ce5fcfc3accf3a07a729779d0b86c5d0309a4764c897d86c11089be61da160"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:3dcf1978be02153c6a31692d4fbcc2a3f1db9da36039ead23173bc256ee3b91b"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:eedf97be7bc3dbc8addcef4142f4b4164066df0c6f36397ae4aaed3eb187d8ab"}, - {file = "pydantic_core-2.14.6-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:d5f916acf8afbcab6bacbb376ba7dc61f845367901ecd5e328fc4d4aef2fcab0"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:8a14c192c1d724c3acbfb3f10a958c55a2638391319ce8078cb36c02283959b9"}, - {file = "pydantic_core-2.14.6-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:0348b1dc6b76041516e8a854ff95b21c55f5a411c3297d2ca52f5528e49d8411"}, - {file = "pydantic_core-2.14.6-cp39-none-win32.whl", hash = "sha256:de2a0645a923ba57c5527497daf8ec5df69c6eadf869e9cd46e86349146e5975"}, - {file = "pydantic_core-2.14.6-cp39-none-win_amd64.whl", hash = "sha256:aca48506a9c20f68ee61c87f2008f81f8ee99f8d7f0104bff3c47e2d148f89d9"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_10_7_x86_64.whl", hash = "sha256:d5c28525c19f5bb1e09511669bb57353d22b94cf8b65f3a8d141c389a55dec95"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:78d0768ee59baa3de0f4adac9e3748b4b1fffc52143caebddfd5ea2961595277"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:8b93785eadaef932e4fe9c6e12ba67beb1b3f1e5495631419c784ab87e975670"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:a874f21f87c485310944b2b2734cd6d318765bcbb7515eead33af9641816506e"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b89f4477d915ea43b4ceea6756f63f0288941b6443a2b28c69004fe07fde0d0d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:172de779e2a153d36ee690dbc49c6db568d7b33b18dc56b69a7514aecbcf380d"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:dfcebb950aa7e667ec226a442722134539e77c575f6cfaa423f24371bb8d2e94"}, - {file = "pydantic_core-2.14.6-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:55a23dcd98c858c0db44fc5c04fc7ed81c4b4d33c653a7c45ddaebf6563a2f66"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-macosx_10_7_x86_64.whl", hash = "sha256:4241204e4b36ab5ae466ecec5c4c16527a054c69f99bba20f6f75232a6a534e2"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e574de99d735b3fc8364cba9912c2bec2da78775eba95cbb225ef7dda6acea24"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:1302a54f87b5cd8528e4d6d1bf2133b6aa7c6122ff8e9dc5220fbc1e07bffebd"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8e81e4b55930e5ffab4a68db1af431629cf2e4066dbdbfef65348b8ab804ea8"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:c99462ffc538717b3e60151dfaf91125f637e801f5ab008f81c402f1dff0cd0f"}, - {file = "pydantic_core-2.14.6-pp37-pypy37_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:e4cf2d5829f6963a5483ec01578ee76d329eb5caf330ecd05b3edd697e7d768a"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_10_7_x86_64.whl", hash = "sha256:cf10b7d58ae4a1f07fccbf4a0a956d705356fea05fb4c70608bb6fa81d103cda"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-macosx_11_0_arm64.whl", hash = "sha256:399ac0891c284fa8eb998bcfa323f2234858f5d2efca3950ae58c8f88830f145"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9c6a5c79b28003543db3ba67d1df336f253a87d3112dac3a51b94f7d48e4c0e1"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:599c87d79cab2a6a2a9df4aefe0455e61e7d2aeede2f8577c1b7c0aec643ee8e"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:43e166ad47ba900f2542a80d83f9fc65fe99eb63ceec4debec160ae729824052"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:3a0b5db001b98e1c649dd55afa928e75aa4087e587b9524a4992316fa23c9fba"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:747265448cb57a9f37572a488a57d873fd96bf51e5bb7edb52cfb37124516da4"}, - {file = "pydantic_core-2.14.6-pp38-pypy38_pp73-win_amd64.whl", hash = "sha256:7ebe3416785f65c28f4f9441e916bfc8a54179c8dea73c23023f7086fa601c5d"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_10_7_x86_64.whl", hash = "sha256:86c963186ca5e50d5c8287b1d1c9d3f8f024cbe343d048c5bd282aec2d8641f2"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:e0641b506486f0b4cd1500a2a65740243e8670a2549bb02bc4556a83af84ae03"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:71d72ca5eaaa8d38c8df16b7deb1a2da4f650c41b58bb142f3fb75d5ad4a611f"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:27e524624eace5c59af499cd97dc18bb201dc6a7a2da24bfc66ef151c69a5f2a"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:a3dde6cac75e0b0902778978d3b1646ca9f438654395a362cb21d9ad34b24acf"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:00646784f6cd993b1e1c0e7b0fdcbccc375d539db95555477771c27555e3c556"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:23598acb8ccaa3d1d875ef3b35cb6376535095e9405d91a3d57a8c7db5d29341"}, - {file = "pydantic_core-2.14.6-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:7f41533d7e3cf9520065f610b41ac1c76bc2161415955fbcead4981b22c7611e"}, - {file = "pydantic_core-2.14.6.tar.gz", hash = "sha256:1fd0c1d395372843fba13a51c28e3bb9d59bd7aebfeb17358ffaaa1e4dbbe948"}, + {file = "pydantic_core-2.16.2-cp310-cp310-macosx_10_12_x86_64.whl", hash = "sha256:3fab4e75b8c525a4776e7630b9ee48aea50107fea6ca9f593c98da3f4d11bf7c"}, + {file = "pydantic_core-2.16.2-cp310-cp310-macosx_11_0_arm64.whl", hash = "sha256:8bde5b48c65b8e807409e6f20baee5d2cd880e0fad00b1a811ebc43e39a00ab2"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2924b89b16420712e9bb8192396026a8fbd6d8726224f918353ac19c4c043d2a"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:16aa02e7a0f539098e215fc193c8926c897175d64c7926d00a36188917717a05"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:936a787f83db1f2115ee829dd615c4f684ee48ac4de5779ab4300994d8af325b"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:459d6be6134ce3b38e0ef76f8a672924460c455d45f1ad8fdade36796df1ddc8"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:4f9ee4febb249c591d07b2d4dd36ebcad0ccd128962aaa1801508320896575ef"}, + {file = "pydantic_core-2.16.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:40a0bd0bed96dae5712dab2aba7d334a6c67cbcac2ddfca7dbcc4a8176445990"}, + {file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:870dbfa94de9b8866b37b867a2cb37a60c401d9deb4a9ea392abf11a1f98037b"}, + {file = "pydantic_core-2.16.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:308974fdf98046db28440eb3377abba274808bf66262e042c412eb2adf852731"}, + {file = "pydantic_core-2.16.2-cp310-none-win32.whl", hash = "sha256:a477932664d9611d7a0816cc3c0eb1f8856f8a42435488280dfbf4395e141485"}, + {file = "pydantic_core-2.16.2-cp310-none-win_amd64.whl", hash = "sha256:8f9142a6ed83d90c94a3efd7af8873bf7cefed2d3d44387bf848888482e2d25f"}, + {file = "pydantic_core-2.16.2-cp311-cp311-macosx_10_12_x86_64.whl", hash = "sha256:406fac1d09edc613020ce9cf3f2ccf1a1b2f57ab00552b4c18e3d5276c67eb11"}, + {file = "pydantic_core-2.16.2-cp311-cp311-macosx_11_0_arm64.whl", hash = "sha256:ce232a6170dd6532096cadbf6185271e4e8c70fc9217ebe105923ac105da9978"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:a90fec23b4b05a09ad988e7a4f4e081711a90eb2a55b9c984d8b74597599180f"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:8aafeedb6597a163a9c9727d8a8bd363a93277701b7bfd2749fbefee2396469e"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:9957433c3a1b67bdd4c63717eaf174ebb749510d5ea612cd4e83f2d9142f3fc8"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:b0d7a9165167269758145756db43a133608a531b1e5bb6a626b9ee24bc38a8f7"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:dffaf740fe2e147fedcb6b561353a16243e654f7fe8e701b1b9db148242e1272"}, + {file = "pydantic_core-2.16.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:f8ed79883b4328b7f0bd142733d99c8e6b22703e908ec63d930b06be3a0e7113"}, + {file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:cf903310a34e14651c9de056fcc12ce090560864d5a2bb0174b971685684e1d8"}, + {file = "pydantic_core-2.16.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:46b0d5520dbcafea9a8645a8164658777686c5c524d381d983317d29687cce97"}, + {file = "pydantic_core-2.16.2-cp311-none-win32.whl", hash = "sha256:70651ff6e663428cea902dac297066d5c6e5423fda345a4ca62430575364d62b"}, + {file = "pydantic_core-2.16.2-cp311-none-win_amd64.whl", hash = "sha256:98dc6f4f2095fc7ad277782a7c2c88296badcad92316b5a6e530930b1d475ebc"}, + {file = "pydantic_core-2.16.2-cp311-none-win_arm64.whl", hash = "sha256:ef6113cd31411eaf9b39fc5a8848e71c72656fd418882488598758b2c8c6dfa0"}, + {file = "pydantic_core-2.16.2-cp312-cp312-macosx_10_12_x86_64.whl", hash = "sha256:88646cae28eb1dd5cd1e09605680c2b043b64d7481cdad7f5003ebef401a3039"}, + {file = "pydantic_core-2.16.2-cp312-cp312-macosx_11_0_arm64.whl", hash = "sha256:7b883af50eaa6bb3299780651e5be921e88050ccf00e3e583b1e92020333304b"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:7bf26c2e2ea59d32807081ad51968133af3025c4ba5753e6a794683d2c91bf6e"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:99af961d72ac731aae2a1b55ccbdae0733d816f8bfb97b41909e143de735f522"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:02906e7306cb8c5901a1feb61f9ab5e5c690dbbeaa04d84c1b9ae2a01ebe9379"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:d5362d099c244a2d2f9659fb3c9db7c735f0004765bbe06b99be69fbd87c3f15"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3ac426704840877a285d03a445e162eb258924f014e2f074e209d9b4ff7bf380"}, + {file = "pydantic_core-2.16.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:b94cbda27267423411c928208e89adddf2ea5dd5f74b9528513f0358bba019cb"}, + {file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:6db58c22ac6c81aeac33912fb1af0e930bc9774166cdd56eade913d5f2fff35e"}, + {file = "pydantic_core-2.16.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:396fdf88b1b503c9c59c84a08b6833ec0c3b5ad1a83230252a9e17b7dfb4cffc"}, + {file = "pydantic_core-2.16.2-cp312-none-win32.whl", hash = "sha256:7c31669e0c8cc68400ef0c730c3a1e11317ba76b892deeefaf52dcb41d56ed5d"}, + {file = "pydantic_core-2.16.2-cp312-none-win_amd64.whl", hash = "sha256:a3b7352b48fbc8b446b75f3069124e87f599d25afb8baa96a550256c031bb890"}, + {file = "pydantic_core-2.16.2-cp312-none-win_arm64.whl", hash = "sha256:a9e523474998fb33f7c1a4d55f5504c908d57add624599e095c20fa575b8d943"}, + {file = "pydantic_core-2.16.2-cp38-cp38-macosx_10_12_x86_64.whl", hash = "sha256:ae34418b6b389d601b31153b84dce480351a352e0bb763684a1b993d6be30f17"}, + {file = "pydantic_core-2.16.2-cp38-cp38-macosx_11_0_arm64.whl", hash = "sha256:732bd062c9e5d9582a30e8751461c1917dd1ccbdd6cafb032f02c86b20d2e7ec"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e4b52776a2e3230f4854907a1e0946eec04d41b1fc64069ee774876bbe0eab55"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:ef551c053692b1e39e3f7950ce2296536728871110e7d75c4e7753fb30ca87f4"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:ebb892ed8599b23fa8f1799e13a12c87a97a6c9d0f497525ce9858564c4575a4"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:aa6c8c582036275997a733427b88031a32ffa5dfc3124dc25a730658c47a572f"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e4ba0884a91f1aecce75202473ab138724aa4fb26d7707f2e1fa6c3e68c84fbf"}, + {file = "pydantic_core-2.16.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:7924e54f7ce5d253d6160090ddc6df25ed2feea25bfb3339b424a9dd591688bc"}, + {file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:69a7b96b59322a81c2203be537957313b07dd333105b73db0b69212c7d867b4b"}, + {file = "pydantic_core-2.16.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:7e6231aa5bdacda78e96ad7b07d0c312f34ba35d717115f4b4bff6cb87224f0f"}, + {file = "pydantic_core-2.16.2-cp38-none-win32.whl", hash = "sha256:41dac3b9fce187a25c6253ec79a3f9e2a7e761eb08690e90415069ea4a68ff7a"}, + {file = "pydantic_core-2.16.2-cp38-none-win_amd64.whl", hash = "sha256:f685dbc1fdadb1dcd5b5e51e0a378d4685a891b2ddaf8e2bba89bd3a7144e44a"}, + {file = "pydantic_core-2.16.2-cp39-cp39-macosx_10_12_x86_64.whl", hash = "sha256:55749f745ebf154c0d63d46c8c58594d8894b161928aa41adbb0709c1fe78b77"}, + {file = "pydantic_core-2.16.2-cp39-cp39-macosx_11_0_arm64.whl", hash = "sha256:b30b0dd58a4509c3bd7eefddf6338565c4905406aee0c6e4a5293841411a1286"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:18de31781cdc7e7b28678df7c2d7882f9692ad060bc6ee3c94eb15a5d733f8f7"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_armv7l.manylinux2014_armv7l.whl", hash = "sha256:5864b0242f74b9dd0b78fd39db1768bc3f00d1ffc14e596fd3e3f2ce43436a33"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_ppc64le.manylinux2014_ppc64le.whl", hash = "sha256:b8f9186ca45aee030dc8234118b9c0784ad91a0bb27fc4e7d9d6608a5e3d386c"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_s390x.manylinux2014_s390x.whl", hash = "sha256:cc6f6c9be0ab6da37bc77c2dda5f14b1d532d5dbef00311ee6e13357a418e646"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:aa057095f621dad24a1e906747179a69780ef45cc8f69e97463692adbcdae878"}, + {file = "pydantic_core-2.16.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:6ad84731a26bcfb299f9eab56c7932d46f9cad51c52768cace09e92a19e4cf55"}, + {file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:3b052c753c4babf2d1edc034c97851f867c87d6f3ea63a12e2700f159f5c41c3"}, + {file = "pydantic_core-2.16.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:e0f686549e32ccdb02ae6f25eee40cc33900910085de6aa3790effd391ae10c2"}, + {file = "pydantic_core-2.16.2-cp39-none-win32.whl", hash = "sha256:7afb844041e707ac9ad9acad2188a90bffce2c770e6dc2318be0c9916aef1469"}, + {file = "pydantic_core-2.16.2-cp39-none-win_amd64.whl", hash = "sha256:9da90d393a8227d717c19f5397688a38635afec89f2e2d7af0df037f3249c39a"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_10_12_x86_64.whl", hash = "sha256:5f60f920691a620b03082692c378661947d09415743e437a7478c309eb0e4f82"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-macosx_11_0_arm64.whl", hash = "sha256:47924039e785a04d4a4fa49455e51b4eb3422d6eaacfde9fc9abf8fdef164e8a"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:e6294e76b0380bb7a61eb8a39273c40b20beb35e8c87ee101062834ced19c545"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:fe56851c3f1d6f5384b3051c536cc81b3a93a73faf931f404fef95217cf1e10d"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:9d776d30cde7e541b8180103c3f294ef7c1862fd45d81738d156d00551005784"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:72f7919af5de5ecfaf1eba47bf9a5d8aa089a3340277276e5636d16ee97614d7"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:4bfcbde6e06c56b30668a0c872d75a7ef3025dc3c1823a13cf29a0e9b33f67e8"}, + {file = "pydantic_core-2.16.2-pp310-pypy310_pp73-win_amd64.whl", hash = "sha256:ff7c97eb7a29aba230389a2661edf2e9e06ce616c7e35aa764879b6894a44b25"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_10_12_x86_64.whl", hash = "sha256:9b5f13857da99325dcabe1cc4e9e6a3d7b2e2c726248ba5dd4be3e8e4a0b6d0e"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-macosx_11_0_arm64.whl", hash = "sha256:a7e41e3ada4cca5f22b478c08e973c930e5e6c7ba3588fb8e35f2398cdcc1545"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:60eb8ceaa40a41540b9acae6ae7c1f0a67d233c40dc4359c256ad2ad85bdf5e5"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7beec26729d496a12fd23cf8da9944ee338c8b8a17035a560b585c36fe81af20"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-manylinux_2_5_i686.manylinux1_i686.whl", hash = "sha256:22c5f022799f3cd6741e24f0443ead92ef42be93ffda0d29b2597208c94c3753"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_aarch64.whl", hash = "sha256:eca58e319f4fd6df004762419612122b2c7e7d95ffafc37e890252f869f3fb2a"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-musllinux_1_1_x86_64.whl", hash = "sha256:ed957db4c33bc99895f3a1672eca7e80e8cda8bd1e29a80536b4ec2153fa9804"}, + {file = "pydantic_core-2.16.2-pp39-pypy39_pp73-win_amd64.whl", hash = "sha256:459c0d338cc55d099798618f714b21b7ece17eb1a87879f2da20a3ff4c7628e2"}, + {file = "pydantic_core-2.16.2.tar.gz", hash = "sha256:0ba503850d8b8dcc18391f10de896ae51d37fe5fe43dbfb6a35c5c5cad271a06"}, ] [package.dependencies] @@ -2863,71 +2864,71 @@ windows-terminal = ["colorama (>=0.4.6)"] [[package]] name = "pyinstrument" -version = "4.6.1" +version = "4.6.2" description = "Call stack profiler for Python. Shows you why your code is slow!" optional = false python-versions = ">=3.7" files = [ - {file = "pyinstrument-4.6.1-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:73476e4bc6e467ac1b2c3c0dd1f0b71c9061d4de14626676adfdfbb14aa342b4"}, - {file = "pyinstrument-4.6.1-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:4d1da8efd974cf9df52ee03edaee2d3875105ddd00de35aa542760f7c612bdf7"}, - {file = "pyinstrument-4.6.1-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:507be1ee2f2b0c9fba74d622a272640dd6d1b0c9ec3388b2cdeb97ad1e77125f"}, - {file = "pyinstrument-4.6.1-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:95cee6de08eb45754ef4f602ce52b640d1c535d934a6a8733a974daa095def37"}, - {file = "pyinstrument-4.6.1-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c7873e8cec92321251fdf894a72b3c78f4c5c20afdd1fef0baf9042ec843bb04"}, - {file = "pyinstrument-4.6.1-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:a242f6cac40bc83e1f3002b6b53681846dfba007f366971db0bf21e02dbb1903"}, - {file = "pyinstrument-4.6.1-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:97c9660cdb4bd2a43cf4f3ab52cffd22f3ac9a748d913b750178fb34e5e39e64"}, - {file = "pyinstrument-4.6.1-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:e304cd0723e2b18ada5e63c187abf6d777949454c734f5974d64a0865859f0f4"}, - {file = "pyinstrument-4.6.1-cp310-cp310-win32.whl", hash = "sha256:cee21a2d78187dd8a80f72f5d0f1ddb767b2d9800f8bb4d94b6d11f217c22cdb"}, - {file = "pyinstrument-4.6.1-cp310-cp310-win_amd64.whl", hash = "sha256:2000712f71d693fed2f8a1c1638d37b7919124f367b37976d07128d49f1445eb"}, - {file = "pyinstrument-4.6.1-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:a366c6f3dfb11f1739bdc1dee75a01c1563ad0bf4047071e5e77598087df457f"}, - {file = "pyinstrument-4.6.1-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:c6be327be65d934796558aa9cb0f75ce62ebd207d49ad1854610c97b0579ad47"}, - {file = "pyinstrument-4.6.1-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:9e160d9c5d20d3e4ef82269e4e8b246ff09bdf37af5fb8cb8ccca97936d95ad6"}, - {file = "pyinstrument-4.6.1-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6ffbf56605ef21c2fcb60de2fa74ff81f417d8be0c5002a407e414d6ef6dee43"}, - {file = "pyinstrument-4.6.1-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:c92cc4924596d6e8f30a16182bbe90893b1572d847ae12652f72b34a9a17c24a"}, - {file = "pyinstrument-4.6.1-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:f4b48a94d938cae981f6948d9ec603bab2087b178d2095d042d5a48aabaecaab"}, - {file = "pyinstrument-4.6.1-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:e7a386392275bdef4a1849712dc5b74f0023483fca14ef93d0ca27d453548982"}, - {file = "pyinstrument-4.6.1-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:871b131b83e9b1122f2325061c68ed1e861eebcb568c934d2fb193652f077f77"}, - {file = "pyinstrument-4.6.1-cp311-cp311-win32.whl", hash = "sha256:8d8515156dd91f5652d13b5fcc87e634f8fe1c07b68d1d0840348cdd50bf5ace"}, - {file = "pyinstrument-4.6.1-cp311-cp311-win_amd64.whl", hash = "sha256:fb868fbe089036e9f32525a249f4c78b8dc46967612393f204b8234f439c9cc4"}, - {file = "pyinstrument-4.6.1-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:a18cd234cce4f230f1733807f17a134e64a1f1acabf74a14d27f583cf2b183df"}, - {file = "pyinstrument-4.6.1-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:574cfca69150be4ce4461fb224712fbc0722a49b0dc02fa204d02807adf6b5a0"}, - {file = "pyinstrument-4.6.1-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2e02cf505e932eb8ccf561b7527550a67ec14fcae1fe0e25319b09c9c166e914"}, - {file = "pyinstrument-4.6.1-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:832fb2acef9d53701c1ab546564c45fb70a8770c816374f8dd11420d399103c9"}, - {file = "pyinstrument-4.6.1-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:13cb57e9607545623ebe462345b3d0c4caee0125d2d02267043ece8aca8f4ea0"}, - {file = "pyinstrument-4.6.1-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:9be89e7419bcfe8dd6abb0d959d6d9c439c613a4a873514c43d16b48dae697c9"}, - {file = "pyinstrument-4.6.1-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:476785cfbc44e8e1b1ad447398aa3deae81a8df4d37eb2d8bbb0c404eff979cd"}, - {file = "pyinstrument-4.6.1-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:e9cebd90128a3d2fee36d3ccb665c1b9dce75261061b2046203e45c4a8012d54"}, - {file = "pyinstrument-4.6.1-cp312-cp312-win32.whl", hash = "sha256:1d0b76683df2ad5c40eff73607dc5c13828c92fbca36aff1ddf869a3c5a55fa6"}, - {file = "pyinstrument-4.6.1-cp312-cp312-win_amd64.whl", hash = "sha256:c4b7af1d9d6a523cfbfedebcb69202242d5bd0cb89c4e094cc73d5d6e38279bd"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:79ae152f8c6a680a188fb3be5e0f360ac05db5bbf410169a6c40851dfaebcce9"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:07cad2745964c174c65aa75f1bf68a4394d1b4d28f33894837cfd315d1e836f0"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:cb81f66f7f94045d723069cf317453d42375de9ff3c69089cf6466b078ac1db4"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:0ab30ae75969da99e9a529e21ff497c18fdf958e822753db4ae7ed1e67094040"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:f36cb5b644762fb3c86289324bbef17e95f91cd710603ac19444a47f638e8e96"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:8b45075d9dbbc977dbc7007fb22bb0054c6990fbe91bf48dd80c0b96c6307ba7"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:475ac31477f6302e092463896d6a2055f3e6abcd293bad16ff94fc9185308a88"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-win32.whl", hash = "sha256:29172ab3d8609fdf821c3f2562dc61e14f1a8ff5306607c32ca743582d3a760e"}, - {file = "pyinstrument-4.6.1-cp37-cp37m-win_amd64.whl", hash = "sha256:bd176f297c99035127b264369d2bb97a65255f65f8d4e843836baf55ebb3cee4"}, - {file = "pyinstrument-4.6.1-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:23e9b4526978432e9999021da9a545992cf2ac3df5ee82db7beb6908fc4c978c"}, - {file = "pyinstrument-4.6.1-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:2dbcaccc9f456ef95557ec501caeb292119c24446d768cb4fb43578b0f3d572c"}, - {file = "pyinstrument-4.6.1-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2097f63c66c2bc9678c826b9ff0c25acde3ed455590d9dcac21220673fe74fbf"}, - {file = "pyinstrument-4.6.1-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:205ac2e76bd65d61b9611a9ce03d5f6393e34ec5b41dd38808f25d54e6b3e067"}, - {file = "pyinstrument-4.6.1-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:3f414ddf1161976a40fc0a333000e6a4ad612719eac0b8c9bb73f47153187148"}, - {file = "pyinstrument-4.6.1-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:65e62ebfa2cd8fb57eda90006f4505ac4c70da00fc2f05b6d8337d776ea76d41"}, - {file = "pyinstrument-4.6.1-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:d96309df4df10be7b4885797c5f69bb3a89414680ebaec0722d8156fde5268c3"}, - {file = "pyinstrument-4.6.1-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:f3d1ad3bc8ebb4db925afa706aa865c4bfb40d52509f143491ac0df2440ee5d2"}, - {file = "pyinstrument-4.6.1-cp38-cp38-win32.whl", hash = "sha256:dc37cb988c8854eb42bda2e438aaf553536566657d157c4473cc8aad5692a779"}, - {file = "pyinstrument-4.6.1-cp38-cp38-win_amd64.whl", hash = "sha256:2cd4ce750c34a0318fc2d6c727cc255e9658d12a5cf3f2d0473f1c27157bdaeb"}, - {file = "pyinstrument-4.6.1-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:6ca95b21f022e995e062b371d1f42d901452bcbedd2c02f036de677119503355"}, - {file = "pyinstrument-4.6.1-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:ac1e1d7e1f1b64054c4eb04eb4869a7a5eef2261440e73943cc1b1bc3c828c18"}, - {file = "pyinstrument-4.6.1-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:0711845e953fce6ab781221aacffa2a66dbc3289f8343e5babd7b2ea34da6c90"}, - {file = "pyinstrument-4.6.1-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5b7d28582017de35cb64eb4e4fa603e753095108ca03745f5d17295970ee631f"}, - {file = "pyinstrument-4.6.1-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:7be57db08bd366a37db3aa3a6187941ee21196e8b14975db337ddc7d1490649d"}, - {file = "pyinstrument-4.6.1-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:9a0ac0f56860398d2628ce389826ce83fb3a557d0c9a2351e8a2eac6eb869983"}, - {file = "pyinstrument-4.6.1-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:a9045186ff13bc826fef16be53736a85029aae3c6adfe52e666cad00d7ca623b"}, - {file = "pyinstrument-4.6.1-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:6c4c56b6eab9004e92ad8a48bb54913fdd71fc8a748ae42a27b9e26041646f8b"}, - {file = "pyinstrument-4.6.1-cp39-cp39-win32.whl", hash = "sha256:37e989c44b51839d0c97466fa2b623638b9470d56d79e329f359f0e8fa6d83db"}, - {file = "pyinstrument-4.6.1-cp39-cp39-win_amd64.whl", hash = "sha256:5494c5a84fee4309d7d973366ca6b8b9f8ba1d6b254e93b7c506264ef74f2cef"}, - {file = "pyinstrument-4.6.1.tar.gz", hash = "sha256:f4731b27121350f5a983d358d2272fe3df2f538aed058f57217eef7801a89288"}, + {file = "pyinstrument-4.6.2-cp310-cp310-macosx_10_9_universal2.whl", hash = "sha256:7a1b1cd768ea7ea9ab6f5490f7e74431321bcc463e9441dbc2f769617252d9e2"}, + {file = "pyinstrument-4.6.2-cp310-cp310-macosx_10_9_x86_64.whl", hash = "sha256:8a386b9d09d167451fb2111eaf86aabf6e094fed42c15f62ec51d6980bce7d96"}, + {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:23c3e3ca8553b9aac09bd978c73d21b9032c707ac6d803bae6a20ecc048df4a8"}, + {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:5f329f5534ca069420246f5ce57270d975229bcb92a3a3fd6b2ca086527d9764"}, + {file = "pyinstrument-4.6.2-cp310-cp310-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4dcdcc7ba224a0c5edfbd00b0f530f5aed2b26da5aaa2f9af5519d4aa8c7e41"}, + {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_aarch64.whl", hash = "sha256:73db0c2c99119c65b075feee76e903b4ed82e59440fe8b5724acf5c7cb24721f"}, + {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_i686.whl", hash = "sha256:da58f265326f3cf3975366ccb8b39014f1e69ff8327958a089858d71c633d654"}, + {file = "pyinstrument-4.6.2-cp310-cp310-musllinux_1_1_x86_64.whl", hash = "sha256:feebcf860f955401df30d029ec8de7a0c5515d24ea809736430fd1219686fe14"}, + {file = "pyinstrument-4.6.2-cp310-cp310-win32.whl", hash = "sha256:b2b66ff0b16c8ecf1ec22de001cfff46872b2c163c62429055105564eef50b2e"}, + {file = "pyinstrument-4.6.2-cp310-cp310-win_amd64.whl", hash = "sha256:8d104b7a7899d5fa4c5bf1ceb0c1a070615a72c5dc17bc321b612467ad5c5d88"}, + {file = "pyinstrument-4.6.2-cp311-cp311-macosx_10_9_universal2.whl", hash = "sha256:62f6014d2b928b181a52483e7c7b82f2c27e22c577417d1681153e5518f03317"}, + {file = "pyinstrument-4.6.2-cp311-cp311-macosx_10_9_x86_64.whl", hash = "sha256:dcb5c8d763c5df55131670ba2a01a8aebd0d490a789904a55eb6a8b8d497f110"}, + {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:6ed4e8c6c84e0e6429ba7008a66e435ede2d8cb027794c20923c55669d9c5633"}, + {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:6c0f0e1d8f8c70faa90ff57f78ac0dda774b52ea0bfb2d9f0f41ce6f3e7c869e"}, + {file = "pyinstrument-4.6.2-cp311-cp311-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:8b3c44cb037ad0d6e9d9a48c14d856254ada641fbd0ae9de40da045fc2226a2a"}, + {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_aarch64.whl", hash = "sha256:be9901f17ac2f527c352f2fdca3d717c1d7f2ce8a70bad5a490fc8cc5d2a6007"}, + {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_i686.whl", hash = "sha256:8a9791bf8916c1cf439c202fded32de93354b0f57328f303d71950b0027c7811"}, + {file = "pyinstrument-4.6.2-cp311-cp311-musllinux_1_1_x86_64.whl", hash = "sha256:d6162615e783c59e36f2d7caf903a7e3ecb6b32d4a4ae8907f2760b2ef395bf6"}, + {file = "pyinstrument-4.6.2-cp311-cp311-win32.whl", hash = "sha256:28af084aa84bbfd3620ebe71d5f9a0deca4451267f363738ca824f733de55056"}, + {file = "pyinstrument-4.6.2-cp311-cp311-win_amd64.whl", hash = "sha256:dd6007d3c2e318e09e582435dd8d111cccf30d342af66886b783208813caf3d7"}, + {file = "pyinstrument-4.6.2-cp312-cp312-macosx_10_9_universal2.whl", hash = "sha256:e3813c8ecfab9d7d855c5f0f71f11793cf1507f40401aa33575c7fd613577c23"}, + {file = "pyinstrument-4.6.2-cp312-cp312-macosx_10_9_x86_64.whl", hash = "sha256:6c761372945e60fc1396b7a49f30592e8474e70a558f1a87346d27c8c4ce50f7"}, + {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:4fba3244e94c117bf4d9b30b8852bbdcd510e7329fdd5c7c8b3799e00a9215a8"}, + {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:803ac64e526473d64283f504df3b0d5c2c203ea9603cab428641538ffdc753a7"}, + {file = "pyinstrument-4.6.2-cp312-cp312-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:e2e554b1bb0df78f5ce8a92df75b664912ca93aa94208386102af454ec31b647"}, + {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_aarch64.whl", hash = "sha256:7c671057fad22ee3ded897a6a361204ea2538e44c1233cad0e8e30f6d27f33db"}, + {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_i686.whl", hash = "sha256:d02f31fa13a9e8dc702a113878419deba859563a32474c9f68e04619d43d6f01"}, + {file = "pyinstrument-4.6.2-cp312-cp312-musllinux_1_1_x86_64.whl", hash = "sha256:b55983a884f083f93f0fc6d12ff8df0acd1e2fb0580d2f4c7bfe6def33a84b58"}, + {file = "pyinstrument-4.6.2-cp312-cp312-win32.whl", hash = "sha256:fdc0a53b27e5d8e47147489c7dab596ddd1756b1e053217ef5bc6718567099ff"}, + {file = "pyinstrument-4.6.2-cp312-cp312-win_amd64.whl", hash = "sha256:dd5c53a0159126b5ce7cbc4994433c9c671e057c85297ff32645166a06ad2c50"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-macosx_10_9_x86_64.whl", hash = "sha256:b082df0bbf71251a7f4880a12ed28421dba84ea7110bb376e0533067a4eaff40"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:90350533396071cb2543affe01e40bf534c35cb0d4b8fa9fdb0f052f9ca2cfe3"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:67268bb0d579330cff40fd1c90b8510363ca1a0e7204225840614068658dab77"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:20e15b4e1d29ba0b7fc81aac50351e0dc0d7e911e93771ebc3f408e864a2c93b"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_aarch64.whl", hash = "sha256:2e625fc6ffcd4fd420493edd8276179c3f784df207bef4c2192725c1b310534c"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_i686.whl", hash = "sha256:113d2fc534c9ca7b6b5661d6ada05515bf318f6eb34e8d05860fe49eb7cfe17e"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-musllinux_1_1_x86_64.whl", hash = "sha256:3098cd72b71a322a72dafeb4ba5c566465e193d2030adad4c09566bd2f89bf4f"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-win32.whl", hash = "sha256:08fdc7f88c989316fa47805234c37a40fafe7b614afd8ae863f0afa9d1707b37"}, + {file = "pyinstrument-4.6.2-cp37-cp37m-win_amd64.whl", hash = "sha256:5ebeba952c0056dcc9b9355328c78c4b5c2a33b4b4276a9157a3ab589f3d1bac"}, + {file = "pyinstrument-4.6.2-cp38-cp38-macosx_10_9_universal2.whl", hash = "sha256:34e59e91c88ec9ad5630c0964eca823949005e97736bfa838beb4789e94912a2"}, + {file = "pyinstrument-4.6.2-cp38-cp38-macosx_10_9_x86_64.whl", hash = "sha256:cd0320c39e99e3c0a3129d1ed010ac41e5a7eb96fb79900d270080a97962e995"}, + {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:46992e855d630575ec635eeca0068a8ddf423d4fd32ea0875a94e9f8688f0b95"}, + {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:1e474c56da636253dfdca7cd1998b240d6b39f7ed34777362db69224fcf053b1"}, + {file = "pyinstrument-4.6.2-cp38-cp38-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:d4b559322f30509ad8f082561792352d0805b3edfa508e492a36041fdc009259"}, + {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_aarch64.whl", hash = "sha256:06a8578b2943eb1dbbf281e1e59e44246acfefd79e1b06d4950f01b693de12af"}, + {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_i686.whl", hash = "sha256:7bd3da31c46f1c1cb7ae89031725f6a1d1015c2041d9c753fe23980f5f9fd86c"}, + {file = "pyinstrument-4.6.2-cp38-cp38-musllinux_1_1_x86_64.whl", hash = "sha256:e63f4916001aa9c625976a50779282e0a5b5e9b17c52a50ef4c651e468ed5b88"}, + {file = "pyinstrument-4.6.2-cp38-cp38-win32.whl", hash = "sha256:32ec8db6896b94af790a530e1e0edad4d0f941a0ab8dd9073e5993e7ea46af7d"}, + {file = "pyinstrument-4.6.2-cp38-cp38-win_amd64.whl", hash = "sha256:a59fc4f7db738a094823afe6422509fa5816a7bf74e768ce5a7a2ddd91af40ac"}, + {file = "pyinstrument-4.6.2-cp39-cp39-macosx_10_9_universal2.whl", hash = "sha256:3a165e0d2deb212d4cf439383982a831682009e1b08733c568cac88c89784e62"}, + {file = "pyinstrument-4.6.2-cp39-cp39-macosx_10_9_x86_64.whl", hash = "sha256:7ba858b3d6f6e5597c641edcc0e7e464f85aba86d71bc3b3592cb89897bf43f6"}, + {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_17_aarch64.manylinux2014_aarch64.whl", hash = "sha256:2fd8e547cf3df5f0ec6e4dffbe2e857f6b28eda51b71c3c0b5a2fc0646527835"}, + {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_5_i686.manylinux1_i686.manylinux_2_17_i686.manylinux2014_i686.whl", hash = "sha256:0de2c1714a37a820033b19cf134ead43299a02662f1379140974a9ab733c5f3a"}, + {file = "pyinstrument-4.6.2-cp39-cp39-manylinux_2_5_x86_64.manylinux1_x86_64.manylinux_2_17_x86_64.manylinux2014_x86_64.whl", hash = "sha256:01fc45dedceec3df81668d702bca6d400d956c8b8494abc206638c167c78dfd9"}, + {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_aarch64.whl", hash = "sha256:5b6e161ef268d43ee6bbfae7fd2cdd0a52c099ddd21001c126ca1805dc906539"}, + {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_i686.whl", hash = "sha256:6ba8e368d0421f15ba6366dfd60ec131c1b46505d021477e0f865d26cf35a605"}, + {file = "pyinstrument-4.6.2-cp39-cp39-musllinux_1_1_x86_64.whl", hash = "sha256:edca46f04a573ac2fb11a84b937844e6a109f38f80f4b422222fb5be8ecad8cb"}, + {file = "pyinstrument-4.6.2-cp39-cp39-win32.whl", hash = "sha256:baf375953b02fe94d00e716f060e60211ede73f49512b96687335f7071adb153"}, + {file = "pyinstrument-4.6.2-cp39-cp39-win_amd64.whl", hash = "sha256:af1a953bce9fd530040895d01ff3de485e25e1576dccb014f76ba9131376fcad"}, + {file = "pyinstrument-4.6.2.tar.gz", hash = "sha256:0002ee517ed8502bbda6eb2bb1ba8f95a55492fcdf03811ba13d4806e50dd7f6"}, ] [package.extras] @@ -3012,17 +3013,17 @@ testing = ["coverage (==6.2)", "mypy (==0.931)"] [[package]] name = "pytest-asyncio" -version = "0.23.3" +version = "0.23.4" description = "Pytest support for asyncio" optional = false python-versions = ">=3.8" files = [ - {file = "pytest-asyncio-0.23.3.tar.gz", hash = "sha256:af313ce900a62fbe2b1aed18e37ad757f1ef9940c6b6a88e2954de38d6b1fb9f"}, - {file = "pytest_asyncio-0.23.3-py3-none-any.whl", hash = "sha256:37a9d912e8338ee7b4a3e917381d1c95bfc8682048cb0fbc35baba316ec1faba"}, + {file = "pytest-asyncio-0.23.4.tar.gz", hash = "sha256:2143d9d9375bf372a73260e4114541485e84fca350b0b6b92674ca56ff5f7ea2"}, + {file = "pytest_asyncio-0.23.4-py3-none-any.whl", hash = "sha256:b0079dfac14b60cd1ce4691fbfb1748fe939db7d0234b5aba97197d10fbe0fef"}, ] [package.dependencies] -pytest = ">=7.0.0" +pytest = ">=7.0.0,<8" [package.extras] docs = ["sphinx (>=5.3)", "sphinx-rtd-theme (>=1.0)"] @@ -3069,13 +3070,13 @@ testing = ["fields", "hunter", "process-tests", "pytest-xdist", "six", "virtuale [[package]] name = "pytest-django" -version = "4.7.0" +version = "4.8.0" description = "A Django plugin for pytest." optional = false python-versions = ">=3.8" files = [ - {file = "pytest-django-4.7.0.tar.gz", hash = "sha256:92d6fd46b1d79b54fb6b060bbb39428073396cec717d5f2e122a990d4b6aa5e8"}, - {file = "pytest_django-4.7.0-py3-none-any.whl", hash = "sha256:4e1c79d5261ade2dd58d91208017cd8f62cb4710b56e012ecd361d15d5d662a2"}, + {file = "pytest-django-4.8.0.tar.gz", hash = "sha256:5d054fe011c56f3b10f978f41a8efb2e5adfc7e680ef36fb571ada1f24779d90"}, + {file = "pytest_django-4.8.0-py3-none-any.whl", hash = "sha256:ca1ddd1e0e4c227cf9e3e40a6afc6d106b3e70868fd2ac5798a22501271cd0c7"}, ] [package.dependencies] @@ -3200,17 +3201,17 @@ files = [ [[package]] name = "python-multipart" -version = "0.0.6" +version = "0.0.7" description = "A streaming multipart parser for Python" optional = false python-versions = ">=3.7" files = [ - {file = "python_multipart-0.0.6-py3-none-any.whl", hash = "sha256:ee698bab5ef148b0a760751c261902cd096e57e10558e11aca17646b74ee1c18"}, - {file = "python_multipart-0.0.6.tar.gz", hash = "sha256:e9925a80bb668529f1b67c7fdb0a5dacdd7cbfc6fb0bff3ea443fe22bdd62132"}, + {file = "python_multipart-0.0.7-py3-none-any.whl", hash = "sha256:b1fef9a53b74c795e2347daac8c54b252d9e0df9c619712691c1cc8021bd3c49"}, + {file = "python_multipart-0.0.7.tar.gz", hash = "sha256:288a6c39b06596c1b988bb6794c6fbc80e6c369e35e5062637df256bee0c9af9"}, ] [package.extras] -dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==1.7.3)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] +dev = ["atomicwrites (==1.2.1)", "attrs (==19.2.0)", "coverage (==6.5.0)", "hatch", "invoke (==2.2.0)", "more-itertools (==4.3.0)", "pbr (==4.3.0)", "pluggy (==1.0.0)", "py (==1.11.0)", "pytest (==7.2.0)", "pytest-cov (==4.0.0)", "pytest-timeout (==2.1.0)", "pyyaml (==5.1)"] [[package]] name = "pywin32-ctypes" @@ -3667,13 +3668,13 @@ jeepney = ">=0.6" [[package]] name = "sentry-sdk" -version = "1.39.2" +version = "1.40.0" description = "Python client for Sentry (https://sentry.io)" optional = false python-versions = "*" files = [ - {file = "sentry-sdk-1.39.2.tar.gz", hash = "sha256:24c83b0b41c887d33328a9166f5950dc37ad58f01c9f2fbff6b87a6f1094170c"}, - {file = "sentry_sdk-1.39.2-py2.py3-none-any.whl", hash = "sha256:acaf597b30258fc7663063b291aa99e58f3096e91fe1e6634f4b79f9c1943e8e"}, + {file = "sentry-sdk-1.40.0.tar.gz", hash = "sha256:34ad8cfc9b877aaa2a8eb86bfe5296a467fffe0619b931a05b181c45f6da59bf"}, + {file = "sentry_sdk-1.40.0-py2.py3-none-any.whl", hash = "sha256:78575620331186d32f34b7ece6edea97ce751f58df822547d3ab85517881a27a"}, ] [package.dependencies] @@ -3699,7 +3700,7 @@ huey = ["huey (>=2)"] loguru = ["loguru (>=0.5)"] opentelemetry = ["opentelemetry-distro (>=0.35b0)"] opentelemetry-experimental = ["opentelemetry-distro (>=0.40b0,<1.0)", "opentelemetry-instrumentation-aiohttp-client (>=0.40b0,<1.0)", "opentelemetry-instrumentation-django (>=0.40b0,<1.0)", "opentelemetry-instrumentation-fastapi (>=0.40b0,<1.0)", "opentelemetry-instrumentation-flask (>=0.40b0,<1.0)", "opentelemetry-instrumentation-requests (>=0.40b0,<1.0)", "opentelemetry-instrumentation-sqlite3 (>=0.40b0,<1.0)", "opentelemetry-instrumentation-urllib (>=0.40b0,<1.0)"] -pure-eval = ["asttokens", "executing", "pure_eval"] +pure-eval = ["asttokens", "executing", "pure-eval"] pymongo = ["pymongo (>=3.1)"] pyspark = ["pyspark (>=2.4.4)"] quart = ["blinker (>=1.1)", "quart (>=0.16.1)"] @@ -3801,13 +3802,13 @@ test = ["pytest", "pytest-cov"] [[package]] name = "starlette" -version = "0.35.1" +version = "0.36.3" description = "The little ASGI library that shines." optional = false python-versions = ">=3.8" files = [ - {file = "starlette-0.35.1-py3-none-any.whl", hash = "sha256:50bbbda9baa098e361f398fda0928062abbaf1f54f4fadcbe17c092a01eb9a25"}, - {file = "starlette-0.35.1.tar.gz", hash = "sha256:3e2639dac3520e4f58734ed22553f950d3f3cb1001cd2eaac4d57e8cdc5f66bc"}, + {file = "starlette-0.36.3-py3-none-any.whl", hash = "sha256:13d429aa93a61dc40bf503e8c801db1f1bca3dc706b10ef2434a36123568f044"}, + {file = "starlette-0.36.3.tar.gz", hash = "sha256:90a671733cfb35771d8cc605e0b679d23b992f8dcfad48cc60b38cb29aeb7080"}, ] [package.dependencies] @@ -3815,7 +3816,7 @@ anyio = ">=3.4.0,<5" typing-extensions = {version = ">=3.10.0", markers = "python_version < \"3.10\""} [package.extras] -full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart", "pyyaml"] +full = ["httpx (>=0.22.0)", "itsdangerous", "jinja2", "python-multipart (>=0.0.7)", "pyyaml"] [[package]] name = "starlite" @@ -3908,13 +3909,13 @@ html5tagger = ">=1.2.1" [[package]] name = "trove-classifiers" -version = "2024.1.8" +version = "2024.1.31" description = "Canonical source for classifiers on PyPI (pypi.org)." optional = false python-versions = "*" files = [ - {file = "trove-classifiers-2024.1.8.tar.gz", hash = "sha256:6e36caf430ff6485c4b57a4c6b364a13f6a898d16b9417c6c37467e59c14b05a"}, - {file = "trove_classifiers-2024.1.8-py3-none-any.whl", hash = "sha256:3c1ff4deb10149c7e39ede6e5bbc107def64362ef1ee7590ec98d71fb92f1b6a"}, + {file = "trove-classifiers-2024.1.31.tar.gz", hash = "sha256:bfdfe60bbf64985c524416afb637ecc79c558e0beb4b7f52b0039e01044b0229"}, + {file = "trove_classifiers-2024.1.31-py3-none-any.whl", hash = "sha256:854aba3358f3cf10e5c0916aa533f5a39e27aadd8ade26a54cdc2a93257e39c4"}, ] [[package]] @@ -4067,13 +4068,13 @@ files = [ [[package]] name = "types-protobuf" -version = "4.24.0.20240106" +version = "4.24.0.20240129" description = "Typing stubs for protobuf" optional = false python-versions = ">=3.8" files = [ - {file = "types-protobuf-4.24.0.20240106.tar.gz", hash = "sha256:024f034f3b5e2bb2bbff55ebc4d591ed0d2280d90faceedcb148b9e714a3f3ee"}, - {file = "types_protobuf-4.24.0.20240106-py3-none-any.whl", hash = "sha256:0612ef3156bd80567460a15ac7c109b313f6022f1fee04b4d922ab2789baab79"}, + {file = "types-protobuf-4.24.0.20240129.tar.gz", hash = "sha256:8a83dd3b9b76a33e08d8636c5daa212ace1396418ed91837635fcd564a624891"}, + {file = "types_protobuf-4.24.0.20240129-py3-none-any.whl", hash = "sha256:23be68cc29f3f5213b5c5878ac0151706182874040e220cfb11336f9ee642ead"}, ] [[package]] @@ -4249,13 +4250,13 @@ socks = ["PySocks (>=1.5.6,!=1.5.7,<2.0)"] [[package]] name = "uvicorn" -version = "0.27.0" +version = "0.27.0.post1" description = "The lightning-fast ASGI server." optional = false python-versions = ">=3.8" files = [ - {file = "uvicorn-0.27.0-py3-none-any.whl", hash = "sha256:890b00f6c537d58695d3bb1f28e23db9d9e7a17cbcc76d7457c499935f933e24"}, - {file = "uvicorn-0.27.0.tar.gz", hash = "sha256:c855578045d45625fd027367f7653d249f7c49f9361ba15cf9624186b26b8eb6"}, + {file = "uvicorn-0.27.0.post1-py3-none-any.whl", hash = "sha256:4b85ba02b8a20429b9b205d015cbeb788a12da527f731811b643fd739ef90d5f"}, + {file = "uvicorn-0.27.0.post1.tar.gz", hash = "sha256:54898fcd80c13ff1cd28bf77b04ec9dbd8ff60c5259b499b4b12bb0917f22907"}, ] [package.dependencies] @@ -4834,4 +4835,4 @@ starlite = ["starlite"] [metadata] lock-version = "2.0" python-versions = "^3.8" -content-hash = "84fd992f1e0cab3004c5a6911f373813a62df80fdfe878d49c7378334db31ada" +content-hash = "c45e495e5856ed24bb1a5bf24f1c05dfc669c9064e4f8950f54b281882b17b41" diff --git a/pyproject.toml b/pyproject.toml index 0eb5655292..20f0797ce2 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -50,7 +50,7 @@ opentelemetry-api = {version = "<2", optional = true} opentelemetry-sdk = {version = "<2", optional = true} chalice = {version = "^1.22", optional = true} pydantic = {version = ">1.6.1", optional = true} -python-multipart = {version = ">=0.0.5,<0.0.7", optional = true} +python-multipart = {version = ">=0.0.7", optional = true} sanic = {version = ">=20.12.2", optional = true} aiohttp = {version = "^3.7.4.post0", optional = true} fastapi = {version = ">=0.65.2", optional = true} @@ -83,7 +83,7 @@ pytest-emoji = "^0.2.0" pytest-mock = "^3.10" pytest-snapshot = "^0.9.0" pytest-xdist = {extras = ["psutil"], version = "^3.1.0"} -python-multipart = ">=0.0.5,<0.0.7" +python-multipart = ">=0.0.7" rich = {version = ">=12.5.1,<14.0.0", optional = false} sanic-testing = ">=22.9,<24.0" sentry-sdk = "^1.39.2" @@ -192,8 +192,34 @@ stubPath = "" [tool.ruff] line-length = 88 -select = ["ALL"] target-version = "py38" +fix = true +exclude = [ + ".bzr", + ".direnv", + ".eggs", + ".git", + ".hg", + ".mypy_cache", + ".nox", + ".pants.d", + ".ruff_cache", + ".svn", + ".tox", + ".venv", + "__pypackages__", + "_build", + "buck-out", + "build", + "dist", + "node_modules", + "venv", + "tests/codegen/snapshots" +] +src = ["strawberry", "tests"] + +[tool.ruff.lint] +select = ["ALL"] ignore = [ # https://github.com/astral-sh/ruff/pull/4427 # equivalent to keep-runtime-typing @@ -326,38 +352,14 @@ ignore = [ "FIX002", "FA100", ] -fix = true -exclude = [ - ".bzr", - ".direnv", - ".eggs", - ".git", - ".hg", - ".mypy_cache", - ".nox", - ".pants.d", - ".ruff_cache", - ".svn", - ".tox", - ".venv", - "__pypackages__", - "_build", - "buck-out", - "build", - "dist", - "node_modules", - "venv", - "tests/codegen/snapshots" -] -src = ["strawberry", "tests"] -[tool.ruff.per-file-ignores] +[tool.ruff.lint.per-file-ignores] "strawberry/schema/types/concrete_type.py" = ["TCH002"] "tests/*" = ["RSE102", "SLF001", "TCH001", "TCH002", "TCH003", "ANN001", "ANN201", "PLW0603", "PLC1901", "S603", "S607", "B018"] "strawberry/extensions/tracing/__init__.py" = ["TCH004"] "tests/http/clients/__init__.py" = ["F401"] -[tool.ruff.isort] +[tool.ruff.lint.isort] known-first-party = ["strawberry"] known-third-party = ["django", "graphql"] extra-standard-library = ["typing_extensions"] diff --git a/strawberry/utils/aio.py b/strawberry/utils/aio.py index a20ec97ed1..c6a0068269 100644 --- a/strawberry/utils/aio.py +++ b/strawberry/utils/aio.py @@ -24,7 +24,7 @@ async def aenumerate( i = 0 async for element in iterable: yield i, element - i += 1 + i += 1 # noqa: SIM113 async def aislice( From c926395ff96acd22c2fd0170edc308f8548e288e Mon Sep 17 00:00:00 2001 From: Botberry Date: Tue, 6 Feb 2024 15:23:18 +0000 Subject: [PATCH 07/14] =?UTF-8?q?Release=20=F0=9F=8D=93=200.219.2?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- CHANGELOG.md | 10 ++++++++++ RELEASE.md | 5 ----- pyproject.toml | 2 +- 3 files changed, 11 insertions(+), 6 deletions(-) delete mode 100644 RELEASE.md diff --git a/CHANGELOG.md b/CHANGELOG.md index adb004b973..2df76e27a1 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,6 +1,16 @@ CHANGELOG ========= +0.219.2 - 2024-02-06 +-------------------- + +This releases updates the dependency of `python-multipart` to be at least `0.0.7` (which includes a security fix). + +It also removes the upper bound for `python-multipart` so you can always install the latest version (if compatible) 😊 + +Contributed by [Srikanth](https://github.com/XChikuX) via [PR #3375](https://github.com/strawberry-graphql/strawberry/pull/3375/) + + 0.219.1 - 2024-01-28 -------------------- diff --git a/RELEASE.md b/RELEASE.md deleted file mode 100644 index 6db8a30af0..0000000000 --- a/RELEASE.md +++ /dev/null @@ -1,5 +0,0 @@ -Release type: patch - -This releases updates the dependency of `python-multipart` to be at least `0.0.7` (which includes a security fix). - -It also removes the upper bound for `python-multipart` so you can always install the latest version (if compatible) 😊 diff --git a/pyproject.toml b/pyproject.toml index 20f0797ce2..2a8b186f06 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,7 +1,7 @@ [tool.poetry] name = "strawberry-graphql" packages = [ { include = "strawberry" } ] -version = "0.219.1" +version = "0.219.2" description = "A library for creating GraphQL APIs" authors = ["Patrick Arminio "] license = "MIT" From be9a2d53ccadf018b6754d131dda4ed76476a8d9 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Sun, 11 Feb 2024 16:42:34 +0100 Subject: [PATCH 08/14] Fix URL --- docs/integrations/litestar.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/integrations/litestar.md b/docs/integrations/litestar.md index 31a99ac554..05aba23ae2 100644 --- a/docs/integrations/litestar.md +++ b/docs/integrations/litestar.md @@ -60,7 +60,7 @@ The `make_graphql_controller` function accepts the following options: - `connection_init_wait_timeout` optional, default to `timedelta(minutes=1)`, the maximum time to wait for the connection initialization message when using `graphql-transport-ws` - [protocol](<[https://](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit)>) + [protocol](https://github.com/enisdenjo/graphql-ws/blob/master/PROTOCOL.md#connectioninit) ## context_getter From 3709858ddf3e7502209859856b2d037dc08a2798 Mon Sep 17 00:00:00 2001 From: Doctor <50728601+ThirVondukr@users.noreply.github.com> Date: Mon, 26 Feb 2024 02:08:11 +0300 Subject: [PATCH 09/14] Extend query documentation (#3390) * Extend query documentation Add examples with using decorator, arguments and `strawberry.argument` * [pre-commit.ci] auto fixes from pre-commit.com hooks for more information, see https://pre-commit.ci * Update docs/general/queries.md Co-authored-by: Jonathan Ehwald --------- Co-authored-by: pre-commit-ci[bot] <66853113+pre-commit-ci[bot]@users.noreply.github.com> Co-authored-by: Jonathan Ehwald --- docs/general/queries.md | 54 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 54 insertions(+) diff --git a/docs/general/queries.md b/docs/general/queries.md index 97d01349fb..d509212b54 100644 --- a/docs/general/queries.md +++ b/docs/general/queries.md @@ -44,3 +44,57 @@ schema = strawberry.Schema(query=Query) ``` So now, when requesting the name field, the `get_name` function will be called. + +Alternatively a field can be declared using a decorator: + +```python +@strawberry.type +class Query: + @strawberry.field + def name(self) -> str: + return "Strawberry" +``` + +## Arguments + +GraphQL fields can accept arguments, usually to filter out or retrieve specific +objects: + +```python +FRUITS = [ + "Strawberry", + "Apple", + "Orange", +] + + +@strawberry.type +class Query: + @strawberry.field + def fruit(self, startswith: str) -> str | None: + for fruit in FRUITS: + if fruit.startswith(startswith): + return fruit + return None +``` + +Additional metadata can be added to arguments, for example a custom name and +description using `strawberry.argument` with +[typing.Annotated](https://docs.python.org/3/library/typing.html#typing.Annotated): + +```python +@strawberry.type +class Query: + @strawberry.field + def fruits( + self, + is_tasty: Annotated[ + bool | None, + strawberry.argument( + description="Filters out fruits by whenever they're tasty or not", + deprecation_reason="isTasty argument is deprecated, " + "use fruits(taste:SWEET) instead", + ), + ] = None, + ) -> list[str]: ... +``` From 449463832cdd89916d05bc320879dd74fe0bdb33 Mon Sep 17 00:00:00 2001 From: Patrick Arminio Date: Mon, 26 Feb 2024 13:26:02 +0100 Subject: [PATCH 10/14] Fix link --- docs/general/mutations.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/general/mutations.md b/docs/general/mutations.md index bd6923e74a..ea7d065214 100644 --- a/docs/general/mutations.md +++ b/docs/general/mutations.md @@ -91,7 +91,7 @@ Mutations with void-result go against ### The Input Mutation Extension It is usually useful to use a pattern of defining a mutation that receives a -single [input type](./input-types) argument called `input`. +single [input type](../types/input-types) argument called `input`. Strawberry provides a helper to create a mutation that automatically creates an input type for you, whose attributes are the same as the args in the resolver. From 1a694e46df93ca4b72d9acb649b20225fdc0a33d Mon Sep 17 00:00:00 2001 From: Eudald Dachs Date: Mon, 26 Feb 2024 17:46:24 +0100 Subject: [PATCH 11/14] Fix custom fruit pagination example (#3363) --- docs/guides/relay.md | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/docs/guides/relay.md b/docs/guides/relay.md index 016dee3377..bd991a2fd8 100644 --- a/docs/guides/relay.md +++ b/docs/guides/relay.md @@ -298,7 +298,10 @@ class FruitCustomPaginationConnection(relay.Connection[Fruit]): @strawberry.type class Query: - fruits: FruitCustomPaginationConnection + @relay.connection(FruitCustomPaginationConnection) + def fruits(self) -> Iterable[Fruit]: + # This can be a database query, a generator, an async generator, etc + return all_fruits.values() ``` In the example above we specialized the `FruitCustomPaginationConnection` by From 808d898a9041caffe74e4364314b585413e4e5e2 Mon Sep 17 00:00:00 2001 From: Tejus Prasad Date: Tue, 27 Feb 2024 08:40:57 -0600 Subject: [PATCH 12/14] Fixing Capitalization Typo in LifecycleStep(Same as imports now) (#3399) --- docs/extensions/datadog.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/extensions/datadog.md b/docs/extensions/datadog.md index 0618cba1be..3f57e1494c 100644 --- a/docs/extensions/datadog.md +++ b/docs/extensions/datadog.md @@ -79,7 +79,7 @@ class DataDogExtension(DatadogTracingExtension): **kwargs, ) -> Span: span = super().create_span(lifecycle_step, name, **kwargs) - if lifecycle_step == LifeCycleStep.OPERATION: + if lifecycle_step == LifecycleStep.OPERATION: span.set_tag("graphql.query", self.execution_context.query) return span ``` From f33e45647fd11b3a56395716e1755f41a8a46efe Mon Sep 17 00:00:00 2001 From: Jacob Allen Date: Wed, 28 Feb 2024 09:13:24 -0700 Subject: [PATCH 13/14] Fix misplaced parenthesis (#3401) The implementation given in the docs differs from the implementation actually used. The implementation currently shown in the docs raises an AttributeError when used. It appears that the docs were originally created with an extra stray close paren, and the wrong one was deleted when that was fixed. --- docs/types/scalars.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types/scalars.md b/docs/types/scalars.md index 9ce3e49e7e..b1d97f818d 100644 --- a/docs/types/scalars.md +++ b/docs/types/scalars.md @@ -113,7 +113,7 @@ import strawberry Base64 = strawberry.scalar( NewType("Base64", bytes), serialize=lambda v: base64.b64encode(v).decode("utf-8"), - parse_value=lambda v: base64.b64decode(v).encode("utf-8"), + parse_value=lambda v: base64.b64decode(v.encode("utf-8")), ) From 364d152551c72c122b05f874b53b9f6a67d06fca Mon Sep 17 00:00:00 2001 From: DamonGuzman <106456287+DamonGuzman@users.noreply.github.com> Date: Wed, 28 Feb 2024 10:45:52 -0800 Subject: [PATCH 14/14] Update interfaces.md - Changed one of the examples to be self consistent. It was contradicting itself. (#3384) * Update interfaces.md Edited the Interface documentation so the interface fields are correct. * Update docs/types/interfaces.md Co-authored-by: Patrick Arminio --------- Co-authored-by: Patrick Arminio --- docs/types/interfaces.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/docs/types/interfaces.md b/docs/types/interfaces.md index 07c2e9532d..d3a0fb4d1e 100644 --- a/docs/types/interfaces.md +++ b/docs/types/interfaces.md @@ -146,7 +146,7 @@ class FieldError(Error): class PasswordTooShort(FieldError): message: str field: str - fix: str + min_length: int --- interface Error { message: String!