strawberry-graphql 0.235.1.dev1719337273__py3-none-any.whl → 0.236.0__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- strawberry/__init__.py +17 -11
- strawberry/aiohttp/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/aiohttp/handlers/graphql_ws_handler.py +3 -0
- strawberry/aiohttp/test/client.py +3 -0
- strawberry/aiohttp/views.py +3 -0
- strawberry/annotation.py +19 -22
- strawberry/asgi/__init__.py +3 -3
- strawberry/asgi/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/asgi/handlers/graphql_ws_handler.py +3 -0
- strawberry/asgi/test/client.py +3 -0
- strawberry/chalice/views.py +12 -3
- strawberry/channels/handlers/__init__.py +0 -0
- strawberry/channels/handlers/base.py +5 -5
- strawberry/channels/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/channels/handlers/graphql_ws_handler.py +3 -0
- strawberry/channels/handlers/http_handler.py +5 -2
- strawberry/channels/handlers/ws_handler.py +4 -1
- strawberry/channels/router.py +9 -5
- strawberry/channels/testing.py +11 -4
- strawberry/cli/commands/upgrade/__init__.py +13 -5
- strawberry/cli/commands/upgrade/_fake_progress.py +2 -1
- strawberry/cli/commands/upgrade/_run_codemod.py +18 -1
- strawberry/codegen/exceptions.py +8 -0
- strawberry/codegen/query_codegen.py +16 -7
- strawberry/codegen/types.py +32 -1
- strawberry/codemods/update_imports.py +136 -0
- strawberry/dataloader.py +13 -0
- strawberry/directive.py +52 -4
- strawberry/django/context.py +4 -1
- strawberry/django/test/client.py +3 -0
- strawberry/django/views.py +3 -0
- strawberry/exceptions/__init__.py +5 -5
- strawberry/exceptions/duplicated_type_name.py +1 -1
- strawberry/exceptions/invalid_argument_type.py +3 -3
- strawberry/exceptions/invalid_union_type.py +5 -6
- strawberry/exceptions/missing_arguments_annotations.py +1 -1
- strawberry/exceptions/missing_dependencies.py +10 -2
- strawberry/exceptions/missing_return_annotation.py +1 -1
- strawberry/exceptions/permission_fail_silently_requires_optional.py +3 -3
- strawberry/exceptions/scalar_already_registered.py +1 -1
- strawberry/exceptions/unresolved_field_type.py +2 -2
- strawberry/exceptions/utils/source_finder.py +5 -2
- strawberry/experimental/pydantic/conversion.py +5 -5
- strawberry/experimental/pydantic/conversion_types.py +4 -2
- strawberry/experimental/pydantic/error_type.py +2 -2
- strawberry/experimental/pydantic/fields.py +2 -2
- strawberry/experimental/pydantic/object_type.py +11 -7
- strawberry/experimental/pydantic/utils.py +4 -5
- strawberry/ext/dataclasses/dataclasses.py +2 -1
- strawberry/ext/mypy_plugin.py +10 -8
- strawberry/extensions/add_validation_rules.py +27 -23
- strawberry/extensions/base_extension.py +6 -4
- strawberry/extensions/directives.py +4 -1
- strawberry/extensions/disable_validation.py +15 -12
- strawberry/extensions/field_extension.py +11 -5
- strawberry/extensions/mask_errors.py +3 -0
- strawberry/extensions/max_aliases.py +21 -19
- strawberry/extensions/max_tokens.py +14 -16
- strawberry/extensions/parser_cache.py +22 -19
- strawberry/extensions/pyinstrument.py +4 -8
- strawberry/extensions/query_depth_limiter.py +22 -23
- strawberry/extensions/runner.py +3 -0
- strawberry/extensions/tracing/apollo.py +3 -0
- strawberry/extensions/tracing/datadog.py +7 -2
- strawberry/extensions/tracing/opentelemetry.py +3 -0
- strawberry/extensions/tracing/sentry.py +3 -0
- strawberry/extensions/tracing/utils.py +3 -0
- strawberry/extensions/utils.py +3 -0
- strawberry/extensions/validation_cache.py +23 -20
- strawberry/fastapi/context.py +3 -0
- strawberry/fastapi/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/fastapi/handlers/graphql_ws_handler.py +3 -0
- strawberry/fastapi/router.py +3 -0
- strawberry/federation/argument.py +4 -1
- strawberry/federation/enum.py +5 -3
- strawberry/federation/field.py +6 -3
- strawberry/federation/mutation.py +2 -0
- strawberry/federation/object_type.py +7 -4
- strawberry/federation/scalar.py +43 -20
- strawberry/federation/schema.py +12 -9
- strawberry/federation/schema_directive.py +2 -2
- strawberry/federation/schema_directives.py +19 -1
- strawberry/federation/types.py +5 -2
- strawberry/federation/union.py +27 -8
- strawberry/field_extensions/input_mutation.py +5 -2
- strawberry/file_uploads/scalars.py +3 -1
- strawberry/file_uploads/utils.py +3 -0
- strawberry/flask/views.py +8 -2
- strawberry/http/__init__.py +9 -0
- strawberry/http/async_base_view.py +4 -3
- strawberry/http/base.py +5 -7
- strawberry/http/exceptions.py +3 -0
- strawberry/http/ides.py +3 -0
- strawberry/http/sync_base_view.py +4 -3
- strawberry/http/temporal_response.py +3 -0
- strawberry/http/types.py +5 -2
- strawberry/http/typevars.py +3 -0
- strawberry/litestar/controller.py +6 -0
- strawberry/litestar/handlers/__init__.py +0 -0
- strawberry/litestar/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/litestar/handlers/graphql_ws_handler.py +3 -0
- strawberry/parent.py +27 -21
- strawberry/permission.py +70 -27
- strawberry/printer/ast_from_value.py +4 -1
- strawberry/printer/printer.py +8 -5
- strawberry/quart/views.py +3 -0
- strawberry/relay/exceptions.py +7 -0
- strawberry/relay/fields.py +70 -45
- strawberry/relay/types.py +78 -78
- strawberry/relay/utils.py +10 -1
- strawberry/resolvers.py +3 -0
- strawberry/sanic/context.py +3 -0
- strawberry/sanic/utils.py +10 -8
- strawberry/sanic/views.py +5 -9
- strawberry/scalars.py +6 -2
- strawberry/schema/base.py +7 -4
- strawberry/schema/compat.py +12 -2
- strawberry/schema/config.py +3 -0
- strawberry/schema/exceptions.py +3 -0
- strawberry/schema/execute.py +3 -0
- strawberry/schema/name_converter.py +12 -9
- strawberry/schema/schema.py +46 -9
- strawberry/schema/schema_converter.py +16 -14
- strawberry/schema/types/base_scalars.py +3 -1
- strawberry/schema/types/concrete_type.py +4 -4
- strawberry/schema/types/scalar.py +8 -1
- strawberry/schema/validation_rules/one_of.py +3 -0
- strawberry/schema_codegen/__init__.py +3 -0
- strawberry/schema_directive.py +2 -2
- strawberry/starlite/controller.py +3 -0
- strawberry/starlite/handlers/__init__.py +0 -0
- strawberry/starlite/handlers/graphql_transport_ws_handler.py +3 -0
- strawberry/starlite/handlers/graphql_ws_handler.py +3 -0
- strawberry/subscriptions/__init__.py +6 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/__init__.py +5 -0
- strawberry/subscriptions/protocols/graphql_transport_ws/handlers.py +12 -17
- strawberry/subscriptions/protocols/graphql_transport_ws/types.py +21 -25
- strawberry/subscriptions/protocols/graphql_ws/__init__.py +14 -0
- strawberry/subscriptions/protocols/graphql_ws/handlers.py +8 -5
- strawberry/subscriptions/protocols/graphql_ws/types.py +11 -0
- strawberry/test/client.py +44 -29
- strawberry/tools/create_type.py +27 -8
- strawberry/tools/merge_types.py +5 -3
- strawberry/types/__init__.py +8 -1
- strawberry/{arguments.py → types/arguments.py} +44 -13
- strawberry/{auto.py → types/auto.py} +21 -3
- strawberry/types/{types.py → base.py} +234 -10
- strawberry/{enum.py → types/enum.py} +69 -9
- strawberry/types/execution.py +3 -0
- strawberry/{field.py → types/field.py} +46 -23
- strawberry/types/fields/resolver.py +2 -2
- strawberry/types/graphql.py +3 -0
- strawberry/types/info.py +50 -7
- strawberry/{lazy_type.py → types/lazy_type.py} +50 -0
- strawberry/types/mutation.py +351 -0
- strawberry/types/nodes.py +4 -2
- strawberry/{object_type.py → types/object_type.py} +108 -29
- strawberry/{private.py → types/private.py} +13 -6
- strawberry/{custom_scalar.py → types/scalar.py} +39 -23
- strawberry/types/type_resolver.py +21 -16
- strawberry/{union.py → types/union.py} +24 -9
- strawberry/{unset.py → types/unset.py} +20 -0
- strawberry/utils/aio.py +8 -0
- strawberry/utils/await_maybe.py +3 -0
- strawberry/utils/dataclasses.py +3 -0
- strawberry/utils/debug.py +5 -2
- strawberry/utils/deprecations.py +3 -0
- strawberry/utils/graphql_lexer.py +3 -0
- strawberry/utils/importer.py +3 -0
- strawberry/utils/inspect.py +39 -30
- strawberry/utils/logging.py +3 -0
- strawberry/utils/operation.py +3 -0
- strawberry/utils/str_converters.py +3 -0
- strawberry/utils/typing.py +33 -16
- {strawberry_graphql-0.235.1.dev1719337273.dist-info → strawberry_graphql-0.236.0.dist-info}/METADATA +1 -1
- strawberry_graphql-0.236.0.dist-info/RECORD +255 -0
- strawberry/mutation.py +0 -8
- strawberry/type.py +0 -232
- strawberry_graphql-0.235.1.dev1719337273.dist-info/RECORD +0 -252
- {strawberry_graphql-0.235.1.dev1719337273.dist-info → strawberry_graphql-0.236.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.235.1.dev1719337273.dist-info → strawberry_graphql-0.236.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.235.1.dev1719337273.dist-info → strawberry_graphql-0.236.0.dist-info}/entry_points.txt +0 -0
strawberry/ext/mypy_plugin.py
CHANGED
@@ -92,7 +92,7 @@ FALLBACK_VERSION = Decimal("0.800")
|
|
92
92
|
|
93
93
|
|
94
94
|
class MypyVersion:
|
95
|
-
"""Stores the mypy version to be used by the plugin"""
|
95
|
+
"""Stores the mypy version to be used by the plugin."""
|
96
96
|
|
97
97
|
VERSION: Decimal
|
98
98
|
|
@@ -330,9 +330,11 @@ def add_static_method_to_class(
|
|
330
330
|
return_type: Type,
|
331
331
|
tvar_def: Optional[TypeVarType] = None,
|
332
332
|
) -> None:
|
333
|
-
"""Adds a static method
|
334
|
-
|
335
|
-
|
333
|
+
"""Adds a static method.
|
334
|
+
|
335
|
+
Edited `add_method_to_class` to incorporate static method logic
|
336
|
+
|
337
|
+
https://github.com/python/mypy/blob/9c05d3d19/mypy/plugins/common.py.
|
336
338
|
"""
|
337
339
|
info = cls.info
|
338
340
|
|
@@ -555,22 +557,22 @@ class StrawberryPlugin(Plugin):
|
|
555
557
|
return None
|
556
558
|
|
557
559
|
def _is_strawberry_union(self, fullname: str) -> bool:
|
558
|
-
return fullname == "strawberry.union.union" or fullname.endswith(
|
560
|
+
return fullname == "strawberry.types.union.union" or fullname.endswith(
|
559
561
|
"strawberry.union"
|
560
562
|
)
|
561
563
|
|
562
564
|
def _is_strawberry_enum(self, fullname: str) -> bool:
|
563
|
-
return fullname == "strawberry.enum.enum" or fullname.endswith(
|
565
|
+
return fullname == "strawberry.types.enum.enum" or fullname.endswith(
|
564
566
|
"strawberry.enum"
|
565
567
|
)
|
566
568
|
|
567
569
|
def _is_strawberry_scalar(self, fullname: str) -> bool:
|
568
|
-
return fullname == "strawberry.
|
570
|
+
return fullname == "strawberry.types.scalar.scalar" or fullname.endswith(
|
569
571
|
"strawberry.scalar"
|
570
572
|
)
|
571
573
|
|
572
574
|
def _is_strawberry_lazy_type(self, fullname: str) -> bool:
|
573
|
-
return fullname == "strawberry.lazy_type.LazyType"
|
575
|
+
return fullname == "strawberry.types.lazy_type.LazyType"
|
574
576
|
|
575
577
|
def _is_strawberry_create_type(self, fullname: str) -> bool:
|
576
578
|
# using endswith(.create_type) is not ideal as there might be
|
@@ -9,31 +9,32 @@ if TYPE_CHECKING:
|
|
9
9
|
|
10
10
|
|
11
11
|
class AddValidationRules(SchemaExtension):
|
12
|
-
"""
|
13
|
-
Add graphql-core validation rules
|
12
|
+
"""Add graphql-core validation rules.
|
14
13
|
|
15
14
|
Example:
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
15
|
+
```python
|
16
|
+
import strawberry
|
17
|
+
from strawberry.extensions import AddValidationRules
|
18
|
+
from graphql import ValidationRule, GraphQLError
|
19
|
+
|
20
|
+
|
21
|
+
class MyCustomRule(ValidationRule):
|
22
|
+
def enter_field(self, node, *args) -> None:
|
23
|
+
if node.name.value == "secret_field":
|
24
|
+
self.report_error(GraphQLError("Can't query field 'secret_field'"))
|
25
|
+
|
26
|
+
|
27
|
+
schema = strawberry.Schema(
|
28
|
+
Query,
|
29
|
+
extensions=[
|
30
|
+
AddValidationRules(
|
31
|
+
[
|
32
|
+
MyCustomRule,
|
33
|
+
]
|
34
|
+
),
|
35
|
+
],
|
36
|
+
)
|
37
|
+
```
|
37
38
|
"""
|
38
39
|
|
39
40
|
validation_rules: List[Type[ASTValidationRule]]
|
@@ -46,3 +47,6 @@ class AddValidationRules(SchemaExtension):
|
|
46
47
|
self.execution_context.validation_rules + tuple(self.validation_rules)
|
47
48
|
)
|
48
49
|
yield
|
50
|
+
|
51
|
+
|
52
|
+
__all__ = ["AddValidationRules"]
|
@@ -27,25 +27,25 @@ class SchemaExtension:
|
|
27
27
|
def on_operation( # type: ignore
|
28
28
|
self,
|
29
29
|
) -> AsyncIteratorOrIterator[None]: # pragma: no cover
|
30
|
-
"""Called before and after a GraphQL operation (query / mutation) starts"""
|
30
|
+
"""Called before and after a GraphQL operation (query / mutation) starts."""
|
31
31
|
yield None
|
32
32
|
|
33
33
|
def on_validate( # type: ignore
|
34
34
|
self,
|
35
35
|
) -> AsyncIteratorOrIterator[None]: # pragma: no cover
|
36
|
-
"""Called before and after the validation step"""
|
36
|
+
"""Called before and after the validation step."""
|
37
37
|
yield None
|
38
38
|
|
39
39
|
def on_parse( # type: ignore
|
40
40
|
self,
|
41
41
|
) -> AsyncIteratorOrIterator[None]: # pragma: no cover
|
42
|
-
"""Called before and after the parsing step"""
|
42
|
+
"""Called before and after the parsing step."""
|
43
43
|
yield None
|
44
44
|
|
45
45
|
def on_execute( # type: ignore
|
46
46
|
self,
|
47
47
|
) -> AsyncIteratorOrIterator[None]: # pragma: no cover
|
48
|
-
"""Called before and after the execution step"""
|
48
|
+
"""Called before and after the execution step."""
|
49
49
|
yield None
|
50
50
|
|
51
51
|
def resolve(
|
@@ -70,3 +70,5 @@ HOOK_METHODS: Set[str] = {
|
|
70
70
|
SchemaExtension.on_parse.__name__,
|
71
71
|
SchemaExtension.on_execute.__name__,
|
72
72
|
}
|
73
|
+
|
74
|
+
__all__ = ["SchemaExtension", "Hook", "HOOK_METHODS", "LifecycleStep"]
|
@@ -11,8 +11,8 @@ if TYPE_CHECKING:
|
|
11
11
|
from graphql import DirectiveNode, GraphQLResolveInfo
|
12
12
|
|
13
13
|
from strawberry.directive import StrawberryDirective
|
14
|
-
from strawberry.field import StrawberryField
|
15
14
|
from strawberry.schema.schema import Schema
|
15
|
+
from strawberry.types.field import StrawberryField
|
16
16
|
from strawberry.utils.await_maybe import AwaitableOrValue
|
17
17
|
|
18
18
|
|
@@ -85,3 +85,6 @@ def process_directive(
|
|
85
85
|
if value_parameter:
|
86
86
|
arguments[value_parameter.name] = value
|
87
87
|
return strawberry_directive, arguments
|
88
|
+
|
89
|
+
|
90
|
+
__all__ = ["DirectivesExtension", "DirectivesExtensionSync"]
|
@@ -4,21 +4,21 @@ from strawberry.extensions.base_extension import SchemaExtension
|
|
4
4
|
|
5
5
|
|
6
6
|
class DisableValidation(SchemaExtension):
|
7
|
-
"""
|
8
|
-
Disable query validation
|
7
|
+
"""Disable query validation.
|
9
8
|
|
10
9
|
Example:
|
11
10
|
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
11
|
+
```python
|
12
|
+
import strawberry
|
13
|
+
from strawberry.extensions import DisableValidation
|
14
|
+
|
15
|
+
schema = strawberry.Schema(
|
16
|
+
Query,
|
17
|
+
extensions=[
|
18
|
+
DisableValidation,
|
19
|
+
],
|
20
|
+
)
|
21
|
+
```
|
22
22
|
"""
|
23
23
|
|
24
24
|
def __init__(self) -> None:
|
@@ -29,3 +29,6 @@ class DisableValidation(SchemaExtension):
|
|
29
29
|
def on_operation(self) -> Iterator[None]:
|
30
30
|
self.execution_context.validation_rules = () # remove all validation_rules
|
31
31
|
yield
|
32
|
+
|
33
|
+
|
34
|
+
__all__ = ["DisableValidation"]
|
@@ -7,8 +7,8 @@ from typing import TYPE_CHECKING, Any, Awaitable, Callable, Union
|
|
7
7
|
if TYPE_CHECKING:
|
8
8
|
from typing_extensions import TypeAlias
|
9
9
|
|
10
|
-
from strawberry.field import StrawberryField
|
11
10
|
from strawberry.types import Info
|
11
|
+
from strawberry.types.field import StrawberryField
|
12
12
|
|
13
13
|
|
14
14
|
SyncExtensionResolver: TypeAlias = Callable[..., Any]
|
@@ -44,7 +44,9 @@ class FieldExtension:
|
|
44
44
|
|
45
45
|
class SyncToAsyncExtension(FieldExtension):
|
46
46
|
"""Helper class for mixing async extensions with sync resolvers.
|
47
|
-
|
47
|
+
|
48
|
+
Applied automatically.
|
49
|
+
"""
|
48
50
|
|
49
51
|
async def resolve_async(
|
50
52
|
self, next_: AsyncExtensionResolver, source: Any, info: Info, **kwargs: Any
|
@@ -67,11 +69,12 @@ def _get_async_resolvers(
|
|
67
69
|
def build_field_extension_resolvers(
|
68
70
|
field: StrawberryField,
|
69
71
|
) -> list[Union[SyncExtensionResolver, AsyncExtensionResolver]]:
|
70
|
-
"""
|
72
|
+
"""Builds a list of resolvers for a field with extensions.
|
73
|
+
|
71
74
|
Verifies that all of the field extensions for a given field support
|
72
75
|
sync or async depending on the field resolver.
|
73
|
-
|
74
|
-
use Async extensions on sync resolvers
|
76
|
+
|
77
|
+
Inserts a SyncToAsyncExtension to be able to use Async extensions on sync resolvers
|
75
78
|
Throws a TypeError otherwise.
|
76
79
|
|
77
80
|
Returns True if resolving should be async, False on sync resolving
|
@@ -151,3 +154,6 @@ def build_field_extension_resolvers(
|
|
151
154
|
f"If possible try to change the execution order so that all sync-only "
|
152
155
|
f"extensions are executed first."
|
153
156
|
)
|
157
|
+
|
158
|
+
|
159
|
+
__all__ = ["FieldExtension"]
|
@@ -13,36 +13,35 @@ from strawberry.extensions.add_validation_rules import AddValidationRules
|
|
13
13
|
|
14
14
|
|
15
15
|
class MaxAliasesLimiter(AddValidationRules):
|
16
|
-
"""
|
17
|
-
Add a validator to limit the number of aliases used.
|
16
|
+
"""Add a validator to limit the number of aliases used.
|
18
17
|
|
19
18
|
Example:
|
20
19
|
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
>>> schema = strawberry.Schema(
|
25
|
-
... Query,
|
26
|
-
... extensions=[
|
27
|
-
... MaxAliasesLimiter(max_alias_count=15)
|
28
|
-
... ]
|
29
|
-
... )
|
30
|
-
|
31
|
-
Arguments:
|
20
|
+
```python
|
21
|
+
import strawberry
|
22
|
+
from strawberry.extensions import MaxAliasesLimiter
|
32
23
|
|
33
|
-
|
34
|
-
|
24
|
+
schema = strawberry.Schema(Query, extensions=[MaxAliasesLimiter(max_alias_count=15)])
|
25
|
+
```
|
35
26
|
"""
|
36
27
|
|
37
|
-
def __init__(
|
38
|
-
|
39
|
-
|
40
|
-
|
28
|
+
def __init__(self, max_alias_count: int) -> None:
|
29
|
+
"""Initialize the MaxAliasesLimiter.
|
30
|
+
|
31
|
+
Args:
|
32
|
+
max_alias_count: The maximum number of aliases allowed in a GraphQL document.
|
33
|
+
"""
|
41
34
|
validator = create_validator(max_alias_count)
|
42
35
|
super().__init__([validator])
|
43
36
|
|
44
37
|
|
45
38
|
def create_validator(max_alias_count: int) -> Type[ValidationRule]:
|
39
|
+
"""Create a validator that checks the number of aliases in a document.
|
40
|
+
|
41
|
+
Args:
|
42
|
+
max_alias_count: The maximum number of aliases allowed in a GraphQL document.
|
43
|
+
"""
|
44
|
+
|
46
45
|
class MaxAliasesValidator(ValidationRule):
|
47
46
|
def __init__(self, validation_context: ValidationContext) -> None:
|
48
47
|
document = validation_context.document
|
@@ -82,3 +81,6 @@ def count_fields_with_alias(
|
|
82
81
|
result += count_fields_with_alias(selection)
|
83
82
|
|
84
83
|
return result
|
84
|
+
|
85
|
+
|
86
|
+
__all__ = ["MaxAliasesLimiter"]
|
@@ -4,25 +4,15 @@ from strawberry.extensions.base_extension import SchemaExtension
|
|
4
4
|
|
5
5
|
|
6
6
|
class MaxTokensLimiter(SchemaExtension):
|
7
|
-
"""
|
8
|
-
Add a validator to limit the number of tokens in a GraphQL document.
|
7
|
+
"""Add a validator to limit the number of tokens in a GraphQL document.
|
9
8
|
|
10
9
|
Example:
|
10
|
+
```python
|
11
|
+
import strawberry
|
12
|
+
from strawberry.extensions import MaxTokensLimiter
|
11
13
|
|
12
|
-
|
13
|
-
|
14
|
-
>>>
|
15
|
-
>>> schema = strawberry.Schema(
|
16
|
-
... Query,
|
17
|
-
... extensions=[
|
18
|
-
... MaxTokensLimiter(max_token_count=1000)
|
19
|
-
... ]
|
20
|
-
... )
|
21
|
-
|
22
|
-
Arguments:
|
23
|
-
|
24
|
-
`max_token_count: int`
|
25
|
-
The maximum number of tokens allowed in a GraphQL document.
|
14
|
+
schema = strawberry.Schema(Query, extensions=[MaxTokensLimiter(max_token_count=1000)])
|
15
|
+
```
|
26
16
|
|
27
17
|
The following things are counted as tokens:
|
28
18
|
* various brackets: "{", "}", "(", ")"
|
@@ -37,8 +27,16 @@ class MaxTokensLimiter(SchemaExtension):
|
|
37
27
|
self,
|
38
28
|
max_token_count: int,
|
39
29
|
) -> None:
|
30
|
+
"""Initialize the MaxTokensLimiter.
|
31
|
+
|
32
|
+
Args:
|
33
|
+
max_token_count: The maximum number of tokens allowed in a GraphQL document.
|
34
|
+
"""
|
40
35
|
self.max_token_count = max_token_count
|
41
36
|
|
42
37
|
def on_operation(self) -> Iterator[None]:
|
43
38
|
self.execution_context.parse_options["max_tokens"] = self.max_token_count
|
44
39
|
yield
|
40
|
+
|
41
|
+
|
42
|
+
__all__ = ["MaxTokensLimiter"]
|
@@ -6,31 +6,31 @@ from strawberry.schema.execute import parse_document
|
|
6
6
|
|
7
7
|
|
8
8
|
class ParserCache(SchemaExtension):
|
9
|
-
"""
|
10
|
-
Add LRU caching the parsing step during execution to improve performance.
|
9
|
+
"""Add LRU caching the parsing step during execution to improve performance.
|
11
10
|
|
12
11
|
Example:
|
13
12
|
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
`maxsize: Optional[int]`
|
27
|
-
Set the maxsize of the cache. If `maxsize` is set to `None` then the
|
28
|
-
cache will grow without bound.
|
29
|
-
More info: https://docs.python.org/3/library/functools.html#functools.lru_cache
|
30
|
-
|
13
|
+
```python
|
14
|
+
import strawberry
|
15
|
+
from strawberry.extensions import ParserCache
|
16
|
+
|
17
|
+
schema = strawberry.Schema(
|
18
|
+
Query,
|
19
|
+
extensions=[
|
20
|
+
ParserCache(maxsize=100),
|
21
|
+
],
|
22
|
+
)
|
23
|
+
```
|
31
24
|
"""
|
32
25
|
|
33
26
|
def __init__(self, maxsize: Optional[int] = None) -> None:
|
27
|
+
"""Initialize the ParserCache.
|
28
|
+
|
29
|
+
Args:
|
30
|
+
maxsize: Set the maxsize of the cache. If `maxsize` is set to `None` then the
|
31
|
+
cache will grow without bound.
|
32
|
+
More info: https://docs.python.org/3/library/functools.html#functools.lru_cache
|
33
|
+
"""
|
34
34
|
self.cached_parse_document = lru_cache(maxsize=maxsize)(parse_document)
|
35
35
|
|
36
36
|
def on_parse(self) -> Iterator[None]:
|
@@ -40,3 +40,6 @@ class ParserCache(SchemaExtension):
|
|
40
40
|
execution_context.query, **execution_context.parse_options
|
41
41
|
)
|
42
42
|
yield
|
43
|
+
|
44
|
+
|
45
|
+
__all__ = ["ParserCache"]
|
@@ -9,9 +9,7 @@ from strawberry.extensions.base_extension import SchemaExtension
|
|
9
9
|
|
10
10
|
|
11
11
|
class PyInstrument(SchemaExtension):
|
12
|
-
"""
|
13
|
-
Extension to profile the execution time of resolvers using PyInstrument.
|
14
|
-
"""
|
12
|
+
"""Extension to profile the execution time of resolvers using PyInstrument."""
|
15
13
|
|
16
14
|
def __init__(
|
17
15
|
self,
|
@@ -20,11 +18,6 @@ class PyInstrument(SchemaExtension):
|
|
20
18
|
self._report_path = report_path
|
21
19
|
|
22
20
|
def on_operation(self) -> Iterator[None]:
|
23
|
-
"""
|
24
|
-
Called when an operation is started,
|
25
|
-
in this case we start the profiler and yield
|
26
|
-
then we stop the profiler when the operation is done
|
27
|
-
"""
|
28
21
|
profiler = Profiler()
|
29
22
|
profiler.start()
|
30
23
|
|
@@ -33,3 +26,6 @@ class PyInstrument(SchemaExtension):
|
|
33
26
|
profiler.stop()
|
34
27
|
|
35
28
|
Path(self._report_path, encoding="utf-8").write_text(profiler.output_html())
|
29
|
+
|
30
|
+
|
31
|
+
__all__ = ["PyInstrument"]
|
@@ -81,32 +81,19 @@ ShouldIgnoreType = Callable[[IgnoreContext], bool]
|
|
81
81
|
|
82
82
|
|
83
83
|
class QueryDepthLimiter(AddValidationRules):
|
84
|
-
"""
|
85
|
-
Add a validator to limit the query depth of GraphQL operations
|
84
|
+
"""Add a validator to limit the query depth of GraphQL operations.
|
86
85
|
|
87
86
|
Example:
|
88
87
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
Arguments:
|
100
|
-
|
101
|
-
`max_depth: int`
|
102
|
-
The maximum allowed depth for any operation in a GraphQL document.
|
103
|
-
`callback: Optional[Callable[[Dict[str, int]], None]`
|
104
|
-
Called each time validation runs. Receives an Object which is a
|
105
|
-
map of the depths for each operation.
|
106
|
-
`should_ignore: Optional[ShouldIgnoreType]`
|
107
|
-
Stops recursive depth checking based on a field name and arguments.
|
108
|
-
A function that returns a boolean and conforms to the ShouldIgnoreType
|
109
|
-
function signature.
|
88
|
+
```python
|
89
|
+
import strawberry
|
90
|
+
from strawberry.extensions import QueryDepthLimiter
|
91
|
+
|
92
|
+
schema = strawberry.Schema(
|
93
|
+
Query,
|
94
|
+
extensions=[QueryDepthLimiter(max_depth=4)],
|
95
|
+
)
|
96
|
+
```
|
110
97
|
"""
|
111
98
|
|
112
99
|
def __init__(
|
@@ -115,6 +102,15 @@ class QueryDepthLimiter(AddValidationRules):
|
|
115
102
|
callback: Optional[Callable[[Dict[str, int]], None]] = None,
|
116
103
|
should_ignore: Optional[ShouldIgnoreType] = None,
|
117
104
|
) -> None:
|
105
|
+
"""Initialize the QueryDepthLimiter.
|
106
|
+
|
107
|
+
Args:
|
108
|
+
max_depth: The maximum allowed depth for any operation in a GraphQL document.
|
109
|
+
callback: Called each time validation runs.
|
110
|
+
Receives an Object which is a map of the depths for each operation.
|
111
|
+
should_ignore: Stops recursive depth checking based on a field name and arguments.
|
112
|
+
A function that returns a boolean and conforms to the ShouldIgnoreType function signature.
|
113
|
+
"""
|
118
114
|
if should_ignore is not None and not callable(should_ignore):
|
119
115
|
raise TypeError(
|
120
116
|
"The `should_ignore` argument to "
|
@@ -317,3 +313,6 @@ def is_ignored(node: FieldNode, ignore: Optional[List[IgnoreType]] = None) -> bo
|
|
317
313
|
raise TypeError(f"Invalid ignore option: {rule}")
|
318
314
|
|
319
315
|
return False
|
316
|
+
|
317
|
+
|
318
|
+
__all__ = ["QueryDepthLimiter"]
|
strawberry/extensions/runner.py
CHANGED
@@ -191,3 +191,6 @@ class ApolloTracingExtensionSync(ApolloTracingExtension):
|
|
191
191
|
end_timestamp = self.now()
|
192
192
|
resolver_stats.duration = end_timestamp - start_timestamp
|
193
193
|
self._resolver_stats.append(resolver_stats)
|
194
|
+
|
195
|
+
|
196
|
+
__all__ = ["ApolloTracingExtension", "ApolloTracingExtensionSync"]
|
@@ -43,18 +43,20 @@ class DatadogTracingExtension(SchemaExtension):
|
|
43
43
|
name: str,
|
44
44
|
**kwargs: Any,
|
45
45
|
) -> Span:
|
46
|
-
"""
|
47
|
-
|
46
|
+
"""Create a span with the given name and kwargs.
|
47
|
+
|
48
48
|
You can override this if you want to add more tags to the span.
|
49
49
|
|
50
50
|
Example:
|
51
51
|
|
52
|
+
```python
|
52
53
|
class CustomExtension(DatadogTracingExtension):
|
53
54
|
def create_span(self, lifecycle_step, name, **kwargs):
|
54
55
|
span = super().create_span(lifecycle_step, name, **kwargs)
|
55
56
|
if lifecycle_step == LifeCycleStep.OPERATION:
|
56
57
|
span.set_tag("graphql.query", self.execution_context.query)
|
57
58
|
return span
|
59
|
+
```
|
58
60
|
"""
|
59
61
|
return tracer.trace(
|
60
62
|
name,
|
@@ -173,3 +175,6 @@ class DatadogTracingExtensionSync(DatadogTracingExtension):
|
|
173
175
|
span.set_tag("graphql.path", ".".join(map(str, info.path.as_list())))
|
174
176
|
|
175
177
|
return _next(root, info, *args, **kwargs)
|
178
|
+
|
179
|
+
|
180
|
+
__all__ = ["DatadogTracingExtension", "DatadogTracingExtensionSync"]
|
strawberry/extensions/utils.py
CHANGED
@@ -6,31 +6,31 @@ from strawberry.schema.execute import validate_document
|
|
6
6
|
|
7
7
|
|
8
8
|
class ValidationCache(SchemaExtension):
|
9
|
-
"""
|
10
|
-
Add LRU caching the validation step during execution to improve performance.
|
9
|
+
"""Add LRU caching the validation step during execution to improve performance.
|
11
10
|
|
12
11
|
Example:
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
Arguments:
|
25
|
-
|
26
|
-
`maxsize: Optional[int]`
|
27
|
-
Set the maxsize of the cache. If `maxsize` is set to `None` then the
|
28
|
-
cache will grow without bound.
|
29
|
-
More info: https://docs.python.org/3/library/functools.html#functools.lru_cache
|
30
|
-
|
12
|
+
```python
|
13
|
+
import strawberry
|
14
|
+
from strawberry.extensions import ValidationCache
|
15
|
+
|
16
|
+
schema = strawberry.Schema(
|
17
|
+
Query,
|
18
|
+
extensions=[
|
19
|
+
ValidationCache(maxsize=100),
|
20
|
+
],
|
21
|
+
)
|
22
|
+
```
|
31
23
|
"""
|
32
24
|
|
33
25
|
def __init__(self, maxsize: Optional[int] = None) -> None:
|
26
|
+
"""Initialize the ValidationCache.
|
27
|
+
|
28
|
+
Args:
|
29
|
+
maxsize: Set the maxsize of the cache. If `maxsize` is set to `None` then the
|
30
|
+
cache will grow without bound.
|
31
|
+
|
32
|
+
More info: https://docs.python.org/3/library/functools.html#functools.lru_cache
|
33
|
+
"""
|
34
34
|
self.cached_validate_document = lru_cache(maxsize=maxsize)(validate_document)
|
35
35
|
|
36
36
|
def on_validate(self) -> Iterator[None]:
|
@@ -43,3 +43,6 @@ class ValidationCache(SchemaExtension):
|
|
43
43
|
)
|
44
44
|
execution_context.errors = errors
|
45
45
|
yield
|
46
|
+
|
47
|
+
|
48
|
+
__all__ = ["ValidationCache"]
|