strawberry-graphql 0.279.0.dev1754159379__py3-none-any.whl → 0.280.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 +1 -2
- strawberry/aiohttp/views.py +2 -48
- strawberry/asgi/__init__.py +2 -37
- strawberry/chalice/views.py +7 -75
- strawberry/channels/handlers/http_handler.py +30 -6
- strawberry/cli/commands/upgrade/__init__.py +2 -0
- strawberry/codemods/__init__.py +9 -0
- strawberry/codemods/maybe_optional.py +118 -0
- strawberry/django/views.py +4 -73
- strawberry/experimental/pydantic/_compat.py +1 -0
- strawberry/experimental/pydantic/error_type.py +1 -0
- strawberry/experimental/pydantic/fields.py +1 -0
- strawberry/experimental/pydantic/utils.py +1 -0
- strawberry/fastapi/router.py +8 -4
- strawberry/flask/views.py +4 -74
- strawberry/http/async_base_view.py +5 -31
- strawberry/http/base.py +2 -1
- strawberry/http/exceptions.py +5 -7
- strawberry/http/sync_base_view.py +1 -34
- strawberry/litestar/controller.py +1 -39
- strawberry/quart/views.py +3 -33
- strawberry/sanic/views.py +4 -43
- strawberry/schema/schema.py +2 -0
- strawberry/schema/schema_converter.py +15 -38
- strawberry/schema/validation_rules/maybe_null.py +136 -0
- strawberry/types/arguments.py +16 -2
- strawberry/types/maybe.py +1 -1
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/METADATA +2 -1
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/RECORD +32 -34
- strawberry/pydantic/__init__.py +0 -22
- strawberry/pydantic/error.py +0 -51
- strawberry/pydantic/fields.py +0 -202
- strawberry/pydantic/object_type.py +0 -348
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/entry_points.txt +0 -0
|
@@ -0,0 +1,136 @@
|
|
|
1
|
+
from typing import Any
|
|
2
|
+
|
|
3
|
+
from graphql import (
|
|
4
|
+
ArgumentNode,
|
|
5
|
+
GraphQLError,
|
|
6
|
+
GraphQLNamedType,
|
|
7
|
+
ObjectValueNode,
|
|
8
|
+
ValidationContext,
|
|
9
|
+
ValidationRule,
|
|
10
|
+
get_named_type,
|
|
11
|
+
)
|
|
12
|
+
|
|
13
|
+
from strawberry.types.base import StrawberryMaybe, StrawberryOptional
|
|
14
|
+
from strawberry.utils.str_converters import to_camel_case
|
|
15
|
+
|
|
16
|
+
|
|
17
|
+
class MaybeNullValidationRule(ValidationRule):
|
|
18
|
+
"""Validates that Maybe[T] fields do not receive explicit null values.
|
|
19
|
+
|
|
20
|
+
This rule ensures that:
|
|
21
|
+
- Maybe[T] fields can only be omitted or have non-null values
|
|
22
|
+
- Maybe[T | None] fields can be omitted, null, or have non-null values
|
|
23
|
+
|
|
24
|
+
This provides clear semantics where Maybe[T] means "either present with value or absent"
|
|
25
|
+
and Maybe[T | None] means "present with value, present but null, or absent".
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
def __init__(self, validation_context: ValidationContext) -> None:
|
|
29
|
+
super().__init__(validation_context)
|
|
30
|
+
|
|
31
|
+
def enter_argument(self, node: ArgumentNode, *_args: Any) -> None:
|
|
32
|
+
# Check if this is a null value
|
|
33
|
+
if node.value.kind != "null_value":
|
|
34
|
+
return
|
|
35
|
+
|
|
36
|
+
# Get the argument definition from the schema
|
|
37
|
+
argument_def = self.context.get_argument()
|
|
38
|
+
if not argument_def:
|
|
39
|
+
return
|
|
40
|
+
|
|
41
|
+
# Check if this argument corresponds to a Maybe[T] (not Maybe[T | None])
|
|
42
|
+
# The argument type extensions should contain the Strawberry type info
|
|
43
|
+
strawberry_arg_info = argument_def.extensions.get("strawberry-definition")
|
|
44
|
+
if not strawberry_arg_info:
|
|
45
|
+
return
|
|
46
|
+
|
|
47
|
+
# Get the Strawberry type from the argument info
|
|
48
|
+
field_type = getattr(strawberry_arg_info, "type", None)
|
|
49
|
+
if not field_type:
|
|
50
|
+
return
|
|
51
|
+
|
|
52
|
+
if isinstance(field_type, StrawberryMaybe) and not isinstance(
|
|
53
|
+
field_type.of_type, StrawberryOptional
|
|
54
|
+
):
|
|
55
|
+
# This is Maybe[T] - should not accept null values
|
|
56
|
+
type_name = self._get_type_name(field_type.of_type)
|
|
57
|
+
|
|
58
|
+
self.report_error(
|
|
59
|
+
GraphQLError(
|
|
60
|
+
f"Expected value of type '{type_name}', found null. "
|
|
61
|
+
f"Argument '{node.name.value}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
|
|
62
|
+
f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
|
|
63
|
+
nodes=[node],
|
|
64
|
+
)
|
|
65
|
+
)
|
|
66
|
+
|
|
67
|
+
def enter_object_value(self, node: ObjectValueNode, *_args: Any) -> None:
|
|
68
|
+
# Get the input type for this object
|
|
69
|
+
input_type = get_named_type(self.context.get_input_type())
|
|
70
|
+
if not input_type:
|
|
71
|
+
return
|
|
72
|
+
|
|
73
|
+
# Get the Strawberry type definition from extensions
|
|
74
|
+
strawberry_type = input_type.extensions.get("strawberry-definition")
|
|
75
|
+
if not strawberry_type:
|
|
76
|
+
return
|
|
77
|
+
|
|
78
|
+
# Check each field in the object for null Maybe[T] violations
|
|
79
|
+
self.validate_maybe_fields(node, input_type, strawberry_type)
|
|
80
|
+
|
|
81
|
+
def validate_maybe_fields(
|
|
82
|
+
self, node: ObjectValueNode, input_type: GraphQLNamedType, strawberry_type: Any
|
|
83
|
+
) -> None:
|
|
84
|
+
# Create a map of field names to field nodes for easy lookup
|
|
85
|
+
field_node_map = {field.name.value: field for field in node.fields}
|
|
86
|
+
|
|
87
|
+
# Check each field in the Strawberry type definition
|
|
88
|
+
if not hasattr(strawberry_type, "fields"):
|
|
89
|
+
return
|
|
90
|
+
|
|
91
|
+
for field_def in strawberry_type.fields:
|
|
92
|
+
# Resolve the actual GraphQL field name using the same logic as NameConverter
|
|
93
|
+
if field_def.graphql_name is not None:
|
|
94
|
+
field_name = field_def.graphql_name
|
|
95
|
+
else:
|
|
96
|
+
# Apply auto_camel_case conversion if enabled (default behavior)
|
|
97
|
+
field_name = to_camel_case(field_def.python_name)
|
|
98
|
+
|
|
99
|
+
# Check if this field is present in the input and has a null value
|
|
100
|
+
if field_name in field_node_map:
|
|
101
|
+
field_node = field_node_map[field_name]
|
|
102
|
+
|
|
103
|
+
# Check if this field has a null value
|
|
104
|
+
if field_node.value.kind == "null_value":
|
|
105
|
+
# Check if this is a Maybe[T] (not Maybe[T | None])
|
|
106
|
+
field_type = field_def.type
|
|
107
|
+
if isinstance(field_type, StrawberryMaybe) and not isinstance(
|
|
108
|
+
field_type.of_type, StrawberryOptional
|
|
109
|
+
):
|
|
110
|
+
# This is Maybe[T] - should not accept null values
|
|
111
|
+
type_name = self._get_type_name(field_type.of_type)
|
|
112
|
+
self.report_error(
|
|
113
|
+
GraphQLError(
|
|
114
|
+
f"Expected value of type '{type_name}', found null. "
|
|
115
|
+
f"Field '{field_name}' of type 'Maybe[{type_name}]' cannot be explicitly set to null. "
|
|
116
|
+
f"Use 'Maybe[{type_name} | None]' if you need to allow null values.",
|
|
117
|
+
nodes=[field_node],
|
|
118
|
+
)
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
def _get_type_name(self, type_: Any) -> str:
|
|
122
|
+
"""Get a readable type name for error messages."""
|
|
123
|
+
if hasattr(type_, "__name__"):
|
|
124
|
+
return type_.__name__
|
|
125
|
+
# Handle Strawberry types that don't have __name__
|
|
126
|
+
if hasattr(type_, "of_type") and hasattr(type_.of_type, "__name__"):
|
|
127
|
+
# For StrawberryList, StrawberryOptional, etc.
|
|
128
|
+
return (
|
|
129
|
+
f"list[{type_.of_type.__name__}]"
|
|
130
|
+
if "List" in str(type_.__class__)
|
|
131
|
+
else type_.of_type.__name__
|
|
132
|
+
)
|
|
133
|
+
return str(type_)
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
__all__ = ["MaybeNullValidationRule"]
|
strawberry/types/arguments.py
CHANGED
|
@@ -191,10 +191,24 @@ def convert_argument(
|
|
|
191
191
|
from strawberry.relay.types import GlobalID
|
|
192
192
|
|
|
193
193
|
# TODO: move this somewhere else and make it first class
|
|
194
|
-
|
|
194
|
+
# Handle StrawberryMaybe first, since it extends StrawberryOptional
|
|
195
|
+
if isinstance(type_, StrawberryMaybe):
|
|
196
|
+
# Check if this is Maybe[T | None] (has StrawberryOptional as of_type)
|
|
197
|
+
if isinstance(type_.of_type, StrawberryOptional):
|
|
198
|
+
# This is Maybe[T | None] - allows null values
|
|
199
|
+
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
200
|
+
|
|
201
|
+
return Some(res)
|
|
202
|
+
|
|
203
|
+
# This is Maybe[T] - validation for null values is handled by MaybeNullValidationRule
|
|
204
|
+
# Convert the value and wrap in Some()
|
|
195
205
|
res = convert_argument(value, type_.of_type, scalar_registry, config)
|
|
196
206
|
|
|
197
|
-
return Some(res)
|
|
207
|
+
return Some(res)
|
|
208
|
+
|
|
209
|
+
# Handle regular StrawberryOptional (not Maybe)
|
|
210
|
+
if isinstance(type_, StrawberryOptional):
|
|
211
|
+
return convert_argument(value, type_.of_type, scalar_registry, config)
|
|
198
212
|
|
|
199
213
|
if value is None:
|
|
200
214
|
return None
|
strawberry/types/maybe.py
CHANGED
{strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/METADATA
RENAMED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.3
|
|
2
2
|
Name: strawberry-graphql
|
|
3
|
-
Version: 0.
|
|
3
|
+
Version: 0.280.0
|
|
4
4
|
Summary: A library for creating GraphQL APIs
|
|
5
5
|
License: MIT
|
|
6
6
|
Keywords: graphql,api,rest,starlette,async
|
|
@@ -37,6 +37,7 @@ Requires-Dist: channels (>=3.0.5) ; extra == "channels"
|
|
|
37
37
|
Requires-Dist: fastapi (>=0.65.2) ; extra == "fastapi"
|
|
38
38
|
Requires-Dist: flask (>=1.1) ; extra == "flask"
|
|
39
39
|
Requires-Dist: graphql-core (>=3.2.0,<3.4.0)
|
|
40
|
+
Requires-Dist: lia-web (>=0.2.1)
|
|
40
41
|
Requires-Dist: libcst ; extra == "cli"
|
|
41
42
|
Requires-Dist: libcst ; extra == "debug"
|
|
42
43
|
Requires-Dist: libcst ; extra == "debug-server"
|
{strawberry_graphql-0.279.0.dev1754159379.dist-info → strawberry_graphql-0.280.0.dist-info}/RECORD
RENAMED
|
@@ -1,19 +1,19 @@
|
|
|
1
|
-
strawberry/__init__.py,sha256=
|
|
1
|
+
strawberry/__init__.py,sha256=tavG4mNFBNHhGBoFR2T7fhiCQ7P-ITHify10nkKBOJE,1544
|
|
2
2
|
strawberry/__main__.py,sha256=3U77Eu21mJ-LY27RG-JEnpbh6Z63wGOom4i-EoLtUcY,59
|
|
3
3
|
strawberry/aiohttp/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
4
4
|
strawberry/aiohttp/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
|
|
5
5
|
strawberry/aiohttp/test/client.py,sha256=8FKZTnvawxYpgEICOri-34O3wHRHLhRpjH_Ktp2EupQ,1801
|
|
6
|
-
strawberry/aiohttp/views.py,sha256=
|
|
6
|
+
strawberry/aiohttp/views.py,sha256=95JdROO8LjCpAG1DvYyxDq96kYVfLzzuRJvDjiTqBZg,6656
|
|
7
7
|
strawberry/annotation.py,sha256=68j7Sku1JT7pUTsUMxekWmQMyFdlV1D0jLFjukmmGpQ,15907
|
|
8
|
-
strawberry/asgi/__init__.py,sha256=
|
|
8
|
+
strawberry/asgi/__init__.py,sha256=nX-YyE9I1t-np7sZ9CK02wBj8EYxZj1M4JAozQS9Rp4,7313
|
|
9
9
|
strawberry/asgi/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
|
|
10
10
|
strawberry/asgi/test/client.py,sha256=kp2O5znHWuAB5VVYO8p4XPSTEDDXBSjNz5WHqW0r6GM,1473
|
|
11
11
|
strawberry/chalice/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
12
|
-
strawberry/chalice/views.py,sha256=
|
|
12
|
+
strawberry/chalice/views.py,sha256=9dBOs_sPH7KNuahlvw4zymxG-Bjj24f5st4-OqMek3g,2785
|
|
13
13
|
strawberry/channels/__init__.py,sha256=AVmEwhzGHcTycMCnZYcZFFqZV8tKw9FJN4YXws-vWFA,433
|
|
14
14
|
strawberry/channels/handlers/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
15
15
|
strawberry/channels/handlers/base.py,sha256=3mSvT2HMlOoWr0Y_8y1wwSmvCmB8osy2pEK1Kc5zJ5M,7841
|
|
16
|
-
strawberry/channels/handlers/http_handler.py,sha256=
|
|
16
|
+
strawberry/channels/handlers/http_handler.py,sha256=EmRVgn0AHG9-dNUOU_rgKf0Ppsh8aiVYpXsVWMJKbNE,12461
|
|
17
17
|
strawberry/channels/handlers/ws_handler.py,sha256=lf6nzr0HR9IQ5CEq-GoVCixUmMZO1uLlhdOoBVasyOA,6228
|
|
18
18
|
strawberry/channels/router.py,sha256=DKIbl4zuRBhfvViUVpyu0Rf_WRT41E6uZC-Yic9Ltvo,2024
|
|
19
19
|
strawberry/channels/testing.py,sha256=dc9mvSm9YdNOUgQk5ou5K4iE2h6TP5quKnk4Xdtn-IY,6558
|
|
@@ -25,7 +25,7 @@ strawberry/cli/commands/export_schema.py,sha256=pyp_Q3BiO7lFH0L3mNPvr7UF8hlhcoUP
|
|
|
25
25
|
strawberry/cli/commands/locate_definition.py,sha256=aJJ_KeAnV-c8zTdWIhzcHUilUmCpqsmrVy24qHbyWKk,1001
|
|
26
26
|
strawberry/cli/commands/schema_codegen.py,sha256=G6eV08a51sjVxCm3jn75oPn9hC8YarKiAKOY5bpTuKU,749
|
|
27
27
|
strawberry/cli/commands/server.py,sha256=qj5wn22HvyJDzwnWzduIWRnS912XvD7GRhPGJkbLaz4,2217
|
|
28
|
-
strawberry/cli/commands/upgrade/__init__.py,sha256=
|
|
28
|
+
strawberry/cli/commands/upgrade/__init__.py,sha256=yj7OxtXhvYdV-P072VFrLnbQmtREnYMLn7iku8gap6k,2596
|
|
29
29
|
strawberry/cli/commands/upgrade/_fake_progress.py,sha256=fefLgJwTXe4kG9RntdEJdzkPPRBK_pZqnmMH-pxD85Y,484
|
|
30
30
|
strawberry/cli/commands/upgrade/_run_codemod.py,sha256=LZd5D1PP65bwVZjBvPPVrZ9t-bfvrafZ__HPBrW2WYA,2168
|
|
31
31
|
strawberry/cli/constants.py,sha256=GhhDZOl9lN4glq50OI1oSbPSGqQXEarZ6r_Grq8pcpI,138
|
|
@@ -40,8 +40,9 @@ strawberry/codegen/plugins/python.py,sha256=GgwxTGd16LPKxGuZBohJYWsarKjWfZY1-aGI
|
|
|
40
40
|
strawberry/codegen/plugins/typescript.py,sha256=LFEK2ZLz4tUukkwZvUTXhsi_cVca3ybsLaatsW5JA5g,3865
|
|
41
41
|
strawberry/codegen/query_codegen.py,sha256=F5z-6qK5KcagagBcZvnjx6iIvdJol17DsBQt7TqhCH4,30539
|
|
42
42
|
strawberry/codegen/types.py,sha256=K5sjzNWDefOzdGtPumXyLuhnlEtd0zZXdPkF15lejk0,4181
|
|
43
|
-
strawberry/codemods/__init__.py,sha256=
|
|
43
|
+
strawberry/codemods/__init__.py,sha256=iXL0fq_VMhmSN3NFkQC4IwQn3pscfES61icODcJAjeo,268
|
|
44
44
|
strawberry/codemods/annotated_unions.py,sha256=T0KqJEmoOdOXVCOHI1G6ECvEVL2tzIRBenysrz3EhPQ,5988
|
|
45
|
+
strawberry/codemods/maybe_optional.py,sha256=PnFbh4kax7UMrsMOsqMF55Q3NN6jMPMxfs_25KmlB_A,4401
|
|
45
46
|
strawberry/codemods/update_imports.py,sha256=4n1m-mxVK7h4FnkrpWgxOOCswIqy9SisApWbh-oSZ3E,4622
|
|
46
47
|
strawberry/dataloader.py,sha256=W4wC-qKrljeKZKH8OgEoGDN_M8aIyhCBLA6g7x04vRQ,7867
|
|
47
48
|
strawberry/directive.py,sha256=GFFUJSuvvr8BV7gRa1XveYIeekuuxlauCpYA9GJonlE,3584
|
|
@@ -50,7 +51,7 @@ strawberry/django/apps.py,sha256=ZWw3Mzv1Cgy0T9xT8Jr2_dkCTZjT5WQABb34iqnu5pc,135
|
|
|
50
51
|
strawberry/django/context.py,sha256=XL85jDGAVnb2pwgm5uRUvIXwlGia3i-8ZVfKihf0T24,655
|
|
51
52
|
strawberry/django/test/__init__.py,sha256=4xxdUZtIISSOwjrcnmox7AvT4WWjowCm5bUuPdQneMg,71
|
|
52
53
|
strawberry/django/test/client.py,sha256=5sAZhCyNiydnQtauI_7H_TRnPfHV3V5d-FKxxDxvTAs,620
|
|
53
|
-
strawberry/django/views.py,sha256=
|
|
54
|
+
strawberry/django/views.py,sha256=jMqy4kb1JJMZbaxutRy9ZMLrqaR2jBzgfkpksE3u0lo,7892
|
|
54
55
|
strawberry/exceptions/__init__.py,sha256=frr0FLykBb8saILFg4pyvhPN0CY3DdSahBUFwK4Hqf0,6628
|
|
55
56
|
strawberry/exceptions/conflicting_arguments.py,sha256=FJ5ZlZ_C9O7XS0H9hB0KGRRix0mcB4P6WwIccTJeh-g,1581
|
|
56
57
|
strawberry/exceptions/duplicated_type_name.py,sha256=Yc8UKO_pTtuXZmkEWp1onBdQitkMSMrfvWfeauLQ-ZI,2204
|
|
@@ -75,14 +76,14 @@ strawberry/exceptions/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
|
75
76
|
strawberry/exceptions/utils/source_finder.py,sha256=wANz2bsXQW2TPES00XDWzDJsdnuAHcnjtM2_iv3eqsA,22566
|
|
76
77
|
strawberry/experimental/__init__.py,sha256=2HP5XtxL8ZKsPp4EDRAbMCqiP7p2V4Cca278JUGxnt0,102
|
|
77
78
|
strawberry/experimental/pydantic/__init__.py,sha256=UpO8wHNXGpoCYp34YStViInO1tsrGsMyhTVubTpJY7Y,255
|
|
78
|
-
strawberry/experimental/pydantic/_compat.py,sha256=
|
|
79
|
+
strawberry/experimental/pydantic/_compat.py,sha256=CUc7SmGA-viYoBgD4L8X483yTGyDKaKMjX3WYWkiohg,9710
|
|
79
80
|
strawberry/experimental/pydantic/conversion.py,sha256=xspWZtbCuhLeStf12X60c5cOrKp4ilVDlnW-tRU0_YY,4242
|
|
80
81
|
strawberry/experimental/pydantic/conversion_types.py,sha256=jf7PR5Q7hgo4J_AuxBK-BVj-8MC6vIg1k1pUfGfGTL8,925
|
|
81
|
-
strawberry/experimental/pydantic/error_type.py,sha256=
|
|
82
|
+
strawberry/experimental/pydantic/error_type.py,sha256=RdmiUY4V0baXCAk80ST-XtCiZbndZaaUSEajQplDAzw,4557
|
|
82
83
|
strawberry/experimental/pydantic/exceptions.py,sha256=pDMPL94ojuSGHxk8H8mI2pfWReG8BhqZ5T2eSxfOi9w,1486
|
|
83
|
-
strawberry/experimental/pydantic/fields.py,sha256=
|
|
84
|
+
strawberry/experimental/pydantic/fields.py,sha256=NcB38JYk29fPwJWtoHkIvwTfqD2Ekf7fJ57GjvvK6mQ,2265
|
|
84
85
|
strawberry/experimental/pydantic/object_type.py,sha256=qoTQXO4qdno0M2oQv0sll7lqeyul_WDNmoSZpm5V14s,12863
|
|
85
|
-
strawberry/experimental/pydantic/utils.py,sha256=
|
|
86
|
+
strawberry/experimental/pydantic/utils.py,sha256=URSzmcK2KzNGsLv4RyFdFfJnr-ARNLkkM0D4CjijVQU,4035
|
|
86
87
|
strawberry/ext/LICENSE,sha256=_oY0TZg0b_sW0--0T44aMTpy2e2zF1Kiyn8E1qDiivo,1249
|
|
87
88
|
strawberry/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
88
89
|
strawberry/ext/dataclasses/LICENSE,sha256=WZgm35K_3NJwLqxpEHJJi7CWxVrwTumEz5D3Dtd7WnA,13925
|
|
@@ -114,7 +115,7 @@ strawberry/extensions/utils.py,sha256=sjhxItHzbDhqHtnR63WbE35qzHhTyf9NSffidet79H
|
|
|
114
115
|
strawberry/extensions/validation_cache.py,sha256=Fp0bz0HfbMVjaOVfTyetR7Knhic0tthkzB_0kOOyJY0,1447
|
|
115
116
|
strawberry/fastapi/__init__.py,sha256=p5qg9AlkYjNOWKcT4uRiebIpR6pIb1HqDMiDfF5O3tg,147
|
|
116
117
|
strawberry/fastapi/context.py,sha256=O_cDNppfUJJecM0ZU_RJ-dhdF0o1x39JfYvYg-7uob4,684
|
|
117
|
-
strawberry/fastapi/router.py,sha256=
|
|
118
|
+
strawberry/fastapi/router.py,sha256=ssH9VnWfYNjYQ9Ldbxk1dPO3u59NBVe_XEEcX64AQDk,12089
|
|
118
119
|
strawberry/federation/__init__.py,sha256=Pw01N0rG9o0NaUxXLMNGeW5oLENeWVx_d8Kuef1ES4s,549
|
|
119
120
|
strawberry/federation/argument.py,sha256=rs71S1utiNUd4XOLRa9KVtSMA3yqvKJnR_qdJqX6PPM,860
|
|
120
121
|
strawberry/federation/enum.py,sha256=geyNA00IjUBroBc6EFrTK0n6DGIVyKOeSE_3aqiwUaQ,3151
|
|
@@ -133,31 +134,27 @@ strawberry/file_uploads/__init__.py,sha256=v2-6FGBqnTnMPSUTFOiXpIutDMl-ga0PFtw5t
|
|
|
133
134
|
strawberry/file_uploads/scalars.py,sha256=NRDeB7j8aotqIkz9r62ISTf4DrxQxEZYUuHsX5K16aU,161
|
|
134
135
|
strawberry/file_uploads/utils.py,sha256=-c6TbqUI-Dkb96hWCrZabh6TL2OabBuQNkCarOqgDm4,1181
|
|
135
136
|
strawberry/flask/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
136
|
-
strawberry/flask/views.py,sha256=
|
|
137
|
+
strawberry/flask/views.py,sha256=eFB9s-gVNw8xEmHlxAkiMRlK2CCojQlDrPTf7aVsZvY,4579
|
|
137
138
|
strawberry/http/__init__.py,sha256=8UWXKZ2IG6_nInp9liUj0qMquDNRR-9o--0EMBL-gnQ,1482
|
|
138
|
-
strawberry/http/async_base_view.py,sha256
|
|
139
|
-
strawberry/http/base.py,sha256=
|
|
140
|
-
strawberry/http/exceptions.py,sha256=
|
|
139
|
+
strawberry/http/async_base_view.py,sha256=-n_gD2Wa8wAZcms89qDGX3jMrMNhwdEPZatS4bXIbiM,25688
|
|
140
|
+
strawberry/http/base.py,sha256=TxvzTtHPrRTCQfJK5pbSXCE2AezT2gpKBRrN58a5Mmc,3215
|
|
141
|
+
strawberry/http/exceptions.py,sha256=5uud0ZijcMC7TS9iiqMTre9DVIe04judh8E8nSbwxy8,258
|
|
141
142
|
strawberry/http/ides.py,sha256=WjU0nsMDgr3Bd1ebWkUEkO2d1hk0dI16mLqXyCHqklA,613
|
|
142
143
|
strawberry/http/parse_content_type.py,sha256=CYHO8F9b9DP1gJ1xxPjc9L2GkBwsyC1O_GCEp1QOuG0,381
|
|
143
|
-
strawberry/http/sync_base_view.py,sha256=
|
|
144
|
+
strawberry/http/sync_base_view.py,sha256=FfufahmBBrRHRVTCGNymcLUAbPxmSqCyIS94pPNebBs,10267
|
|
144
145
|
strawberry/http/temporal_response.py,sha256=HTt65g-YxqlPGxjqvH5bzGoU1b3CctVR-9cmCRo5dUo,196
|
|
145
146
|
strawberry/http/types.py,sha256=H0wGOdCO-5tNKZM_6cAtNRwZAjoEXnAC5N0Q7b70AtU,398
|
|
146
147
|
strawberry/http/typevars.py,sha256=Uu6NkKe3h7o29ZWwldq6sJy4ioSSeXODTCDRvY2hUpE,489
|
|
147
148
|
strawberry/litestar/__init__.py,sha256=zsXzg-mglCGUVO9iNXLm-yadoDSCK7k-zuyRqyvAh1w,237
|
|
148
|
-
strawberry/litestar/controller.py,sha256=
|
|
149
|
+
strawberry/litestar/controller.py,sha256=s5vQUy9Xs43gwZU5DAu6jklHocgcEOnbiBj_aPakZsM,13108
|
|
149
150
|
strawberry/parent.py,sha256=JYFp-HGCgwbH2oB4uLSiIO4cVsoPaxX6lfYmxOKPkSg,1362
|
|
150
151
|
strawberry/permission.py,sha256=dSRJMjSCmTlXfvfC24kCSrAk0txTjYKTJ5ZVU5IW91Y,7537
|
|
151
152
|
strawberry/printer/__init__.py,sha256=DmepjmgtkdF5RxK_7yC6qUyRWn56U-9qeZMbkztYB9w,62
|
|
152
153
|
strawberry/printer/ast_from_value.py,sha256=Tkme60qlykbN2m3dNPNMOe65X-wj6EmcDQwgQv7gUkc,4987
|
|
153
154
|
strawberry/printer/printer.py,sha256=5E9w0wDsUv1hvkeXof12277NLMiCVy5MgJ6gSo_NJhQ,19177
|
|
154
155
|
strawberry/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
155
|
-
strawberry/pydantic/__init__.py,sha256=_QAGALzygcRyKE2iiK_rHt4s_d0g3ms0SUP64rEjrYI,592
|
|
156
|
-
strawberry/pydantic/error.py,sha256=EvS2R99CCoe5Oo5Dh3V9Xc6eGcSFpo-r4F5Wq8RjF7U,1271
|
|
157
|
-
strawberry/pydantic/fields.py,sha256=8oBY7Z-sTj6Tt3l9sNl1Wqk2ERxh-Doe2onQYnsGCP4,7188
|
|
158
|
-
strawberry/pydantic/object_type.py,sha256=sxFTE_VSpAcmOm7-EGL-tp0aobjoctOSjVQs34fRcD8,10785
|
|
159
156
|
strawberry/quart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
160
|
-
strawberry/quart/views.py,sha256=
|
|
157
|
+
strawberry/quart/views.py,sha256=otrWlDdbgHooxAjD7Sf-E82B-PmOaNwCN07oF7Bjhsg,6618
|
|
161
158
|
strawberry/relay/__init__.py,sha256=Vi4btvA_g6Cj9Tk_F9GCSegapIf2WqkOWV8y3P0cTCs,553
|
|
162
159
|
strawberry/relay/exceptions.py,sha256=Za0iXLBGZtd1HkesGm4xTr3QOeuyiCAe1hiCCQ2HHvE,4036
|
|
163
160
|
strawberry/relay/fields.py,sha256=eqQOH8JAWZUP52nwaYCZ_z5Jvp69_T_gx1pxjrdgV1k,18284
|
|
@@ -167,7 +164,7 @@ strawberry/resolvers.py,sha256=Vdidc3YFc4-olSQZD_xQ1icyAFbyzqs_8I3eSpMFlA4,260
|
|
|
167
164
|
strawberry/sanic/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
168
165
|
strawberry/sanic/context.py,sha256=qN7I9K_qIqgdbG_FbDl8XMb9aM1PyjIxSo8IAg2Uq8o,844
|
|
169
166
|
strawberry/sanic/utils.py,sha256=XjUVBFuBWfECBCZbx_YtrjQnFTUyIGTo7aISIeB22Gc,1007
|
|
170
|
-
strawberry/sanic/views.py,sha256=
|
|
167
|
+
strawberry/sanic/views.py,sha256=8Tl5pMYnbaju7WYxJImtJTwVi2XZBKWEwnSB-tYbZGw,5682
|
|
171
168
|
strawberry/scalars.py,sha256=CGkG8CIfurXiYhidmW3qwy6M5BF_Mhih3wAEcWx_iBU,2278
|
|
172
169
|
strawberry/schema/__init__.py,sha256=u1QCyDVQExUVDA20kyosKPz3TS5HMCN2NrXclhiFAL4,92
|
|
173
170
|
strawberry/schema/_graphql_core.py,sha256=_ubCP_4ZZ1KwZGLlHTPPcUVPk_hDh6EOp2FxjCfyKxM,1642
|
|
@@ -176,13 +173,14 @@ strawberry/schema/compat.py,sha256=xNpOEDfi-MODpplMGaKuKeQIVcr-tcAaKaU3TlBc1Zs,1
|
|
|
176
173
|
strawberry/schema/config.py,sha256=bkEMn0EkBRg2Tl6ZZH5hpOGBNiAw9QcOclt5dI_Yd1g,1217
|
|
177
174
|
strawberry/schema/exceptions.py,sha256=8gsMxxFDynMvRkUDuVL9Wwxk_zsmo6QoJ2l4NPxd64M,1137
|
|
178
175
|
strawberry/schema/name_converter.py,sha256=JG5JKLr9wp8BMJIvG3_bVkwFdoLGbknNR1Bt75urXN0,6950
|
|
179
|
-
strawberry/schema/schema.py,sha256=
|
|
180
|
-
strawberry/schema/schema_converter.py,sha256=
|
|
176
|
+
strawberry/schema/schema.py,sha256=Tg-_hC2ri0ibM-gncOEsLkTmt5T3HM6UsetfYPa1t4M,39548
|
|
177
|
+
strawberry/schema/schema_converter.py,sha256=pxp2cz5ZWQV7k_FPWKHXOHpvgR_5aXAFQuCluNhWwvQ,40566
|
|
181
178
|
strawberry/schema/types/__init__.py,sha256=oHO3COWhL3L1KLYCJNY1XFf5xt2GGtHiMC-UaYbFfnA,68
|
|
182
179
|
strawberry/schema/types/base_scalars.py,sha256=JRUq0WjEkR9dFewstZnqnZKp0uOEipo4UXNF5dzRf4M,1971
|
|
183
180
|
strawberry/schema/types/concrete_type.py,sha256=axIyFZgdwNv-XYkiqX67464wuFX6Vp0jYATwnBZSUvM,750
|
|
184
181
|
strawberry/schema/types/scalar.py,sha256=bg9AumdmYUBuvaKoEZtP9YKJ7lwMtDMCWFTsZQwpdQY,2375
|
|
185
182
|
strawberry/schema/validation_rules/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
183
|
+
strawberry/schema/validation_rules/maybe_null.py,sha256=RrIq1yV5_2YxIYN7jx8AaY6O_pqxKtylbM1IygFz5z4,5624
|
|
186
184
|
strawberry/schema/validation_rules/one_of.py,sha256=fPuYzCyLT7p9y7dHF_sWTImArTQaEhyF664lZijB1Gw,2629
|
|
187
185
|
strawberry/schema_codegen/__init__.py,sha256=mN4Qmu5Iakht6nHpRpt9hCs8e--oTPlVtDJZJpzgHR4,24364
|
|
188
186
|
strawberry/schema_directive.py,sha256=CbjdX54EIeWGkJu4SgiLR8mph5_8wyNsgJk2oLoQK_0,2023
|
|
@@ -205,7 +203,7 @@ strawberry/tools/__init__.py,sha256=pdGpZx8wpq03VfUZJyF9JtYxZhGqzzxCiipsalWxJX4,
|
|
|
205
203
|
strawberry/tools/create_type.py,sha256=y10LgJnWDFtZB-xHLqpVg5ySqvz5KSFC6PNflogie1Q,2329
|
|
206
204
|
strawberry/tools/merge_types.py,sha256=hUMRRNM28FyPp70jRA3d4svv9WoEBjaNpihBt3DaY0I,1023
|
|
207
205
|
strawberry/types/__init__.py,sha256=baWEdDkkmCcITOhkg2hNUOenrNV1OYdxGE5qgvIRwwU,351
|
|
208
|
-
strawberry/types/arguments.py,sha256=
|
|
206
|
+
strawberry/types/arguments.py,sha256=5Rw_gAVEw1tkBQJuzeYUahAqMGoZU7JwUf4zAME2vqg,11779
|
|
209
207
|
strawberry/types/auto.py,sha256=WZ2cQAI8nREUigBzpzFqIKGjJ_C2VqpAPNe8vPjTciM,3007
|
|
210
208
|
strawberry/types/base.py,sha256=Bfa-5Wen8qR7m6tlSMRRGlGE-chRGMHjQMopfNdbbrk,15197
|
|
211
209
|
strawberry/types/cast.py,sha256=fx86MkLW77GIximBAwUk5vZxSGwDqUA6XicXvz8EXwQ,916
|
|
@@ -217,7 +215,7 @@ strawberry/types/fields/resolver.py,sha256=b6lxfw6AMOUFWm7vs7a9KzNkpR8b_S110DoIo
|
|
|
217
215
|
strawberry/types/graphql.py,sha256=gXKzawwKiow7hvoJhq5ApNJOMUCnKmvTiHaKY5CK1Lw,867
|
|
218
216
|
strawberry/types/info.py,sha256=V3DQMd97tkWSdPIhp7HcelQ2h94-HSCI5zJ7cRO7i58,4907
|
|
219
217
|
strawberry/types/lazy_type.py,sha256=dlP9VcMjZc9sdgriiQGzOZa0TToB6Ee7zpIP8h7TLC0,5079
|
|
220
|
-
strawberry/types/maybe.py,sha256=
|
|
218
|
+
strawberry/types/maybe.py,sha256=3TEY0S2qT_unEdYlPUW50HBuOIIaploZVy3JWpXdeeE,1161
|
|
221
219
|
strawberry/types/mutation.py,sha256=cg-_O2WWnZ-GSwOIv0toSdxlGeY2lhBBxZ24AifJuSM,11978
|
|
222
220
|
strawberry/types/nodes.py,sha256=RwZB43OT9BS3Cqjgq4AazqOfyq_y0GD2ysC86EDBv5U,5134
|
|
223
221
|
strawberry/types/object_type.py,sha256=SdJF2RWDIrh0C99rEW64rbxMaLokG-J8NLybSqkUrcE,15766
|
|
@@ -240,8 +238,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
|
|
|
240
238
|
strawberry/utils/operation.py,sha256=ZgVOw3K2jQuLjNOYUHauF7itJD0QDNoPw9PBi0IYf6k,1234
|
|
241
239
|
strawberry/utils/str_converters.py,sha256=-eH1Cl16IO_wrBlsGM-km4IY0IKsjhjnSNGRGOwQjVM,897
|
|
242
240
|
strawberry/utils/typing.py,sha256=SDvX-Du-9HAV3-XXjqi7Q5f5qPDDFd_gASIITiwBQT4,14073
|
|
243
|
-
strawberry_graphql-0.
|
|
244
|
-
strawberry_graphql-0.
|
|
245
|
-
strawberry_graphql-0.
|
|
246
|
-
strawberry_graphql-0.
|
|
247
|
-
strawberry_graphql-0.
|
|
241
|
+
strawberry_graphql-0.280.0.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
|
|
242
|
+
strawberry_graphql-0.280.0.dist-info/METADATA,sha256=9qNSWDt50fP_5T8ielfg-EmwUme30KmzwbipRfl107c,7426
|
|
243
|
+
strawberry_graphql-0.280.0.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
|
244
|
+
strawberry_graphql-0.280.0.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
|
|
245
|
+
strawberry_graphql-0.280.0.dist-info/RECORD,,
|
strawberry/pydantic/__init__.py
DELETED
|
@@ -1,22 +0,0 @@
|
|
|
1
|
-
"""Strawberry Pydantic integration.
|
|
2
|
-
|
|
3
|
-
This module provides first-class support for Pydantic models in Strawberry GraphQL.
|
|
4
|
-
You can directly decorate Pydantic BaseModel classes to create GraphQL types.
|
|
5
|
-
|
|
6
|
-
Example:
|
|
7
|
-
@strawberry.pydantic.type
|
|
8
|
-
class User(BaseModel):
|
|
9
|
-
name: str
|
|
10
|
-
age: int
|
|
11
|
-
"""
|
|
12
|
-
|
|
13
|
-
from .error import Error
|
|
14
|
-
from .object_type import input as input_decorator
|
|
15
|
-
from .object_type import interface
|
|
16
|
-
from .object_type import type as type_decorator
|
|
17
|
-
|
|
18
|
-
# Re-export with proper names
|
|
19
|
-
input = input_decorator
|
|
20
|
-
type = type_decorator
|
|
21
|
-
|
|
22
|
-
__all__ = ["Error", "input", "interface", "type"]
|
strawberry/pydantic/error.py
DELETED
|
@@ -1,51 +0,0 @@
|
|
|
1
|
-
"""Generic error type for Pydantic validation errors in Strawberry GraphQL.
|
|
2
|
-
|
|
3
|
-
This module provides a generic Error type that can be used to represent
|
|
4
|
-
Pydantic validation errors in GraphQL responses.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from typing import TYPE_CHECKING
|
|
10
|
-
|
|
11
|
-
from strawberry.types.object_type import type as strawberry_type
|
|
12
|
-
|
|
13
|
-
if TYPE_CHECKING:
|
|
14
|
-
from pydantic import ValidationError
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
@strawberry_type
|
|
18
|
-
class ErrorDetail:
|
|
19
|
-
"""Represents a single validation error detail."""
|
|
20
|
-
|
|
21
|
-
type: str
|
|
22
|
-
loc: list[str]
|
|
23
|
-
msg: str
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
@strawberry_type
|
|
27
|
-
class Error:
|
|
28
|
-
"""Generic error type for Pydantic validation errors."""
|
|
29
|
-
|
|
30
|
-
errors: list[ErrorDetail]
|
|
31
|
-
|
|
32
|
-
@staticmethod
|
|
33
|
-
def from_validation_error(exc: ValidationError) -> Error:
|
|
34
|
-
"""Create an Error instance from a Pydantic ValidationError.
|
|
35
|
-
|
|
36
|
-
Args:
|
|
37
|
-
exc: The Pydantic ValidationError to convert
|
|
38
|
-
|
|
39
|
-
Returns:
|
|
40
|
-
An Error instance containing all validation errors
|
|
41
|
-
"""
|
|
42
|
-
return Error(
|
|
43
|
-
errors=[
|
|
44
|
-
ErrorDetail(
|
|
45
|
-
type=error["type"],
|
|
46
|
-
loc=[str(loc) for loc in error["loc"]],
|
|
47
|
-
msg=error["msg"],
|
|
48
|
-
)
|
|
49
|
-
for error in exc.errors()
|
|
50
|
-
]
|
|
51
|
-
)
|
strawberry/pydantic/fields.py
DELETED
|
@@ -1,202 +0,0 @@
|
|
|
1
|
-
"""Field processing utilities for Pydantic models in Strawberry GraphQL.
|
|
2
|
-
|
|
3
|
-
This module provides functions to extract and process fields from Pydantic BaseModel
|
|
4
|
-
classes, converting them to StrawberryField instances that can be used in GraphQL schemas.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
import sys
|
|
10
|
-
from typing import TYPE_CHECKING, Any
|
|
11
|
-
|
|
12
|
-
from strawberry.annotation import StrawberryAnnotation
|
|
13
|
-
from strawberry.experimental.pydantic._compat import PydanticCompat
|
|
14
|
-
from strawberry.experimental.pydantic.utils import get_default_factory_for_field
|
|
15
|
-
from strawberry.types.field import StrawberryField
|
|
16
|
-
from strawberry.types.private import is_private
|
|
17
|
-
from strawberry.utils.typing import get_args, get_origin, is_union
|
|
18
|
-
|
|
19
|
-
if TYPE_CHECKING:
|
|
20
|
-
from pydantic import BaseModel
|
|
21
|
-
from pydantic.fields import FieldInfo
|
|
22
|
-
|
|
23
|
-
from strawberry.experimental.pydantic._compat import lenient_issubclass
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
def replace_pydantic_types(type_: Any, is_input: bool) -> Any:
|
|
27
|
-
"""Replace Pydantic types with their Strawberry equivalents for first-class integration."""
|
|
28
|
-
from pydantic import BaseModel
|
|
29
|
-
|
|
30
|
-
if lenient_issubclass(type_, BaseModel):
|
|
31
|
-
# For first-class integration, check if the type has been decorated
|
|
32
|
-
if hasattr(type_, "__strawberry_definition__"):
|
|
33
|
-
# Return the type itself as it's already a Strawberry type
|
|
34
|
-
return type_
|
|
35
|
-
# If not decorated, raise an error
|
|
36
|
-
from strawberry.experimental.pydantic.exceptions import (
|
|
37
|
-
UnregisteredTypeException,
|
|
38
|
-
)
|
|
39
|
-
|
|
40
|
-
raise UnregisteredTypeException(type_)
|
|
41
|
-
|
|
42
|
-
return type_
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
def replace_types_recursively(
|
|
46
|
-
type_: Any,
|
|
47
|
-
is_input: bool,
|
|
48
|
-
compat: PydanticCompat,
|
|
49
|
-
) -> Any:
|
|
50
|
-
"""Recursively replace Pydantic types with their Strawberry equivalents."""
|
|
51
|
-
# For now, use a simpler approach similar to the experimental module
|
|
52
|
-
basic_type = compat.get_basic_type(type_)
|
|
53
|
-
replaced_type = replace_pydantic_types(basic_type, is_input)
|
|
54
|
-
|
|
55
|
-
origin = get_origin(type_)
|
|
56
|
-
|
|
57
|
-
if not origin or not hasattr(type_, "__args__"):
|
|
58
|
-
return replaced_type
|
|
59
|
-
|
|
60
|
-
converted = tuple(
|
|
61
|
-
replace_types_recursively(t, is_input=is_input, compat=compat)
|
|
62
|
-
for t in get_args(replaced_type)
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
# Handle special cases for typing generics
|
|
66
|
-
from typing import Union as TypingUnion
|
|
67
|
-
from typing import _GenericAlias as TypingGenericAlias
|
|
68
|
-
|
|
69
|
-
if isinstance(replaced_type, TypingGenericAlias):
|
|
70
|
-
return TypingGenericAlias(origin, converted)
|
|
71
|
-
if is_union(replaced_type):
|
|
72
|
-
return TypingUnion[converted]
|
|
73
|
-
|
|
74
|
-
# Handle Annotated types
|
|
75
|
-
from typing import Annotated
|
|
76
|
-
|
|
77
|
-
if origin is Annotated and converted:
|
|
78
|
-
converted = (converted[0],)
|
|
79
|
-
|
|
80
|
-
# For other types, try to use copy_with if available
|
|
81
|
-
if hasattr(replaced_type, "copy_with"):
|
|
82
|
-
return replaced_type.copy_with(converted)
|
|
83
|
-
|
|
84
|
-
# Fallback to origin[converted] for standard generic types
|
|
85
|
-
return origin[converted]
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
def get_type_for_field(field: FieldInfo, is_input: bool, compat: PydanticCompat) -> Any:
|
|
89
|
-
"""Get the GraphQL type for a Pydantic field."""
|
|
90
|
-
outer_type = field.outer_type_
|
|
91
|
-
|
|
92
|
-
replaced_type = replace_types_recursively(outer_type, is_input, compat=compat)
|
|
93
|
-
|
|
94
|
-
if field.is_v1:
|
|
95
|
-
# only pydantic v1 has this Optional logic
|
|
96
|
-
should_add_optional: bool = field.allow_none
|
|
97
|
-
if should_add_optional:
|
|
98
|
-
from typing import Optional
|
|
99
|
-
|
|
100
|
-
return Optional[replaced_type]
|
|
101
|
-
|
|
102
|
-
return replaced_type
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
def _get_pydantic_fields(
|
|
106
|
-
cls: type[BaseModel],
|
|
107
|
-
original_type_annotations: dict[str, type[Any]],
|
|
108
|
-
is_input: bool = False,
|
|
109
|
-
include_computed: bool = False,
|
|
110
|
-
) -> list[StrawberryField]:
|
|
111
|
-
"""Extract StrawberryFields from a Pydantic BaseModel class.
|
|
112
|
-
|
|
113
|
-
This function processes a Pydantic BaseModel and extracts its fields,
|
|
114
|
-
converting them to StrawberryField instances that can be used in GraphQL schemas.
|
|
115
|
-
All fields from the Pydantic model are included by default, except those marked
|
|
116
|
-
with strawberry.Private.
|
|
117
|
-
|
|
118
|
-
Args:
|
|
119
|
-
cls: The Pydantic BaseModel class to extract fields from
|
|
120
|
-
original_type_annotations: Type annotations that may override field types
|
|
121
|
-
is_input: Whether this is for an input type
|
|
122
|
-
include_computed: Whether to include computed fields
|
|
123
|
-
|
|
124
|
-
Returns:
|
|
125
|
-
List of StrawberryField instances
|
|
126
|
-
"""
|
|
127
|
-
fields: list[StrawberryField] = []
|
|
128
|
-
|
|
129
|
-
# Get compatibility layer for this model
|
|
130
|
-
compat = PydanticCompat.from_model(cls)
|
|
131
|
-
|
|
132
|
-
# Extract Pydantic model fields
|
|
133
|
-
model_fields = compat.get_model_fields(cls, include_computed=include_computed)
|
|
134
|
-
|
|
135
|
-
# Get annotations from the class to check for strawberry.Private and other custom fields
|
|
136
|
-
existing_annotations = getattr(cls, "__annotations__", {})
|
|
137
|
-
|
|
138
|
-
# Process each field from the Pydantic model
|
|
139
|
-
for field_name, pydantic_field in model_fields.items():
|
|
140
|
-
# Check if this field is marked as private
|
|
141
|
-
if field_name in existing_annotations:
|
|
142
|
-
field_type = existing_annotations[field_name]
|
|
143
|
-
# Skip private fields - they shouldn't be included in GraphQL schema
|
|
144
|
-
if is_private(field_type):
|
|
145
|
-
continue
|
|
146
|
-
|
|
147
|
-
# Get the field type from the Pydantic model
|
|
148
|
-
field_type = get_type_for_field(pydantic_field, is_input, compat=compat)
|
|
149
|
-
|
|
150
|
-
# Check if there's a custom field definition on the class
|
|
151
|
-
custom_field = getattr(cls, field_name, None)
|
|
152
|
-
if isinstance(custom_field, StrawberryField):
|
|
153
|
-
# Use the custom field but update its type if needed
|
|
154
|
-
strawberry_field = custom_field
|
|
155
|
-
strawberry_field.type_annotation = StrawberryAnnotation.from_annotation(
|
|
156
|
-
field_type
|
|
157
|
-
)
|
|
158
|
-
else:
|
|
159
|
-
# Create a new StrawberryField
|
|
160
|
-
graphql_name = None
|
|
161
|
-
if pydantic_field.has_alias:
|
|
162
|
-
graphql_name = pydantic_field.alias
|
|
163
|
-
|
|
164
|
-
strawberry_field = StrawberryField(
|
|
165
|
-
python_name=field_name,
|
|
166
|
-
graphql_name=graphql_name,
|
|
167
|
-
type_annotation=StrawberryAnnotation.from_annotation(field_type),
|
|
168
|
-
description=pydantic_field.description,
|
|
169
|
-
default_factory=get_default_factory_for_field(
|
|
170
|
-
pydantic_field, compat=compat
|
|
171
|
-
),
|
|
172
|
-
)
|
|
173
|
-
|
|
174
|
-
# Set the origin module for proper type resolution
|
|
175
|
-
origin = cls
|
|
176
|
-
module = sys.modules[origin.__module__]
|
|
177
|
-
|
|
178
|
-
if (
|
|
179
|
-
isinstance(strawberry_field.type_annotation, StrawberryAnnotation)
|
|
180
|
-
and strawberry_field.type_annotation.namespace is None
|
|
181
|
-
):
|
|
182
|
-
strawberry_field.type_annotation.namespace = module.__dict__
|
|
183
|
-
|
|
184
|
-
strawberry_field.origin = origin
|
|
185
|
-
|
|
186
|
-
# Apply any type overrides from original_type_annotations
|
|
187
|
-
if field_name in original_type_annotations:
|
|
188
|
-
strawberry_field.type = original_type_annotations[field_name]
|
|
189
|
-
strawberry_field.type_annotation = StrawberryAnnotation(
|
|
190
|
-
annotation=strawberry_field.type
|
|
191
|
-
)
|
|
192
|
-
|
|
193
|
-
fields.append(strawberry_field)
|
|
194
|
-
|
|
195
|
-
return fields
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
__all__ = [
|
|
199
|
-
"_get_pydantic_fields",
|
|
200
|
-
"replace_pydantic_types",
|
|
201
|
-
"replace_types_recursively",
|
|
202
|
-
]
|