strawberry-graphql 0.278.0__py3-none-any.whl → 0.279.0.dev1754138688__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 +2 -1
- strawberry/experimental/pydantic/_compat.py +0 -1
- strawberry/experimental/pydantic/error_type.py +0 -1
- strawberry/experimental/pydantic/fields.py +0 -1
- strawberry/experimental/pydantic/utils.py +0 -1
- strawberry/pydantic/__init__.py +21 -0
- strawberry/pydantic/fields.py +202 -0
- strawberry/pydantic/object_type.py +348 -0
- {strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/METADATA +1 -1
- {strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/RECORD +13 -10
- {strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/LICENSE +0 -0
- {strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/WHEEL +0 -0
- {strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/entry_points.txt +0 -0
strawberry/__init__.py
CHANGED
@@ -4,7 +4,7 @@ Strawberry is a Python library for GraphQL that aims to stay close to the GraphQ
|
|
4
4
|
specification and allow for a more natural way of defining GraphQL schemas.
|
5
5
|
"""
|
6
6
|
|
7
|
-
from . import experimental, federation, relay
|
7
|
+
from . import experimental, federation, pydantic, relay
|
8
8
|
from .directive import directive, directive_field
|
9
9
|
from .parent import Parent
|
10
10
|
from .permission import BasePermission
|
@@ -54,6 +54,7 @@ __all__ = [
|
|
54
54
|
"interface",
|
55
55
|
"lazy",
|
56
56
|
"mutation",
|
57
|
+
"pydantic",
|
57
58
|
"relay",
|
58
59
|
"scalar",
|
59
60
|
"schema_directive",
|
@@ -0,0 +1,21 @@
|
|
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 .object_type import input as input_decorator
|
14
|
+
from .object_type import interface
|
15
|
+
from .object_type import type as type_decorator
|
16
|
+
|
17
|
+
# Re-export with proper names
|
18
|
+
input = input_decorator
|
19
|
+
type = type_decorator
|
20
|
+
|
21
|
+
__all__ = ["input", "interface", "type"]
|
@@ -0,0 +1,202 @@
|
|
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
|
+
]
|
@@ -0,0 +1,348 @@
|
|
1
|
+
"""Object type decorators for Pydantic models in Strawberry GraphQL.
|
2
|
+
|
3
|
+
This module provides decorators to convert Pydantic BaseModel classes directly
|
4
|
+
into GraphQL types, inputs, and interfaces without requiring a separate wrapper class.
|
5
|
+
"""
|
6
|
+
|
7
|
+
from __future__ import annotations
|
8
|
+
|
9
|
+
from typing import TYPE_CHECKING, Any, Callable, Optional, Union, overload
|
10
|
+
|
11
|
+
if TYPE_CHECKING:
|
12
|
+
import builtins
|
13
|
+
from collections.abc import Sequence
|
14
|
+
|
15
|
+
from strawberry.experimental.pydantic._compat import PydanticCompat
|
16
|
+
from strawberry.experimental.pydantic.conversion import (
|
17
|
+
convert_strawberry_class_to_pydantic_model,
|
18
|
+
)
|
19
|
+
from strawberry.types.base import StrawberryObjectDefinition
|
20
|
+
from strawberry.types.cast import get_strawberry_type_cast
|
21
|
+
from strawberry.utils.str_converters import to_camel_case
|
22
|
+
|
23
|
+
from .fields import _get_pydantic_fields
|
24
|
+
|
25
|
+
if TYPE_CHECKING:
|
26
|
+
from graphql import GraphQLResolveInfo
|
27
|
+
|
28
|
+
from pydantic import BaseModel
|
29
|
+
|
30
|
+
|
31
|
+
def _get_interfaces(cls: builtins.type[Any]) -> list[StrawberryObjectDefinition]:
|
32
|
+
"""Extract interfaces from a class's inheritance hierarchy."""
|
33
|
+
interfaces: list[StrawberryObjectDefinition] = []
|
34
|
+
|
35
|
+
for base in cls.__mro__[1:]: # Exclude current class
|
36
|
+
if hasattr(base, "__strawberry_definition__"):
|
37
|
+
type_definition = base.__strawberry_definition__
|
38
|
+
if type_definition.is_interface:
|
39
|
+
interfaces.append(type_definition)
|
40
|
+
|
41
|
+
return interfaces
|
42
|
+
|
43
|
+
|
44
|
+
def _process_pydantic_type(
|
45
|
+
cls: type[BaseModel],
|
46
|
+
*,
|
47
|
+
name: Optional[str] = None,
|
48
|
+
is_input: bool = False,
|
49
|
+
is_interface: bool = False,
|
50
|
+
description: Optional[str] = None,
|
51
|
+
directives: Optional[Sequence[object]] = (),
|
52
|
+
include_computed: bool = False,
|
53
|
+
) -> type[BaseModel]:
|
54
|
+
"""Process a Pydantic BaseModel class and add GraphQL metadata.
|
55
|
+
|
56
|
+
Args:
|
57
|
+
cls: The Pydantic BaseModel class to process
|
58
|
+
name: The GraphQL type name (defaults to class name)
|
59
|
+
is_input: Whether this is an input type
|
60
|
+
is_interface: Whether this is an interface type
|
61
|
+
description: The GraphQL type description
|
62
|
+
directives: GraphQL directives to apply
|
63
|
+
include_computed: Whether to include computed fields
|
64
|
+
|
65
|
+
Returns:
|
66
|
+
The processed BaseModel class with GraphQL metadata
|
67
|
+
"""
|
68
|
+
# Get the GraphQL type name
|
69
|
+
name = name or to_camel_case(cls.__name__)
|
70
|
+
|
71
|
+
# Get compatibility layer for this model
|
72
|
+
compat = PydanticCompat.from_model(cls)
|
73
|
+
|
74
|
+
# Extract fields using our custom function
|
75
|
+
# All fields from the Pydantic model are included by default, except strawberry.Private fields
|
76
|
+
fields = _get_pydantic_fields(
|
77
|
+
cls=cls,
|
78
|
+
original_type_annotations={},
|
79
|
+
is_input=is_input,
|
80
|
+
include_computed=include_computed,
|
81
|
+
)
|
82
|
+
|
83
|
+
# Get interfaces from inheritance hierarchy
|
84
|
+
interfaces = _get_interfaces(cls)
|
85
|
+
|
86
|
+
# Create the is_type_of method for proper type resolution
|
87
|
+
def is_type_of(obj: Any, _info: GraphQLResolveInfo) -> bool:
|
88
|
+
if (type_cast := get_strawberry_type_cast(obj)) is not None:
|
89
|
+
return type_cast is cls
|
90
|
+
return isinstance(obj, cls)
|
91
|
+
|
92
|
+
# Create the GraphQL type definition
|
93
|
+
cls.__strawberry_definition__ = StrawberryObjectDefinition( # type: ignore
|
94
|
+
name=name,
|
95
|
+
is_input=is_input,
|
96
|
+
is_interface=is_interface,
|
97
|
+
interfaces=interfaces,
|
98
|
+
description=description,
|
99
|
+
directives=directives,
|
100
|
+
origin=cls,
|
101
|
+
extend=False,
|
102
|
+
fields=fields,
|
103
|
+
is_type_of=is_type_of,
|
104
|
+
resolve_type=getattr(cls, "resolve_type", None),
|
105
|
+
)
|
106
|
+
|
107
|
+
# Add the is_type_of method to the class for testing purposes
|
108
|
+
cls.is_type_of = is_type_of # type: ignore
|
109
|
+
|
110
|
+
# Add conversion methods
|
111
|
+
def from_pydantic(
|
112
|
+
instance: BaseModel, extra: Optional[dict[str, Any]] = None
|
113
|
+
) -> BaseModel:
|
114
|
+
"""Convert a Pydantic model instance to a GraphQL-compatible instance."""
|
115
|
+
if extra:
|
116
|
+
# If there are extra fields, create a new instance with them
|
117
|
+
instance_dict = compat.model_dump(instance)
|
118
|
+
instance_dict.update(extra)
|
119
|
+
return cls(**instance_dict)
|
120
|
+
return instance
|
121
|
+
|
122
|
+
def to_pydantic(self: Any, **kwargs: Any) -> BaseModel:
|
123
|
+
"""Convert a GraphQL instance back to a Pydantic model."""
|
124
|
+
if isinstance(self, cls):
|
125
|
+
# If it's already the right type, return it
|
126
|
+
if not kwargs:
|
127
|
+
return self
|
128
|
+
# Create a new instance with the updated kwargs
|
129
|
+
instance_dict = compat.model_dump(self)
|
130
|
+
instance_dict.update(kwargs)
|
131
|
+
return cls(**instance_dict)
|
132
|
+
|
133
|
+
# If it's a different type, convert it
|
134
|
+
return convert_strawberry_class_to_pydantic_model(self, **kwargs)
|
135
|
+
|
136
|
+
# Add conversion methods if they don't exist
|
137
|
+
if not hasattr(cls, "from_pydantic"):
|
138
|
+
cls.from_pydantic = staticmethod(from_pydantic) # type: ignore
|
139
|
+
if not hasattr(cls, "to_pydantic"):
|
140
|
+
cls.to_pydantic = to_pydantic # type: ignore
|
141
|
+
|
142
|
+
return cls
|
143
|
+
|
144
|
+
|
145
|
+
@overload
|
146
|
+
def type(
|
147
|
+
cls: type[BaseModel],
|
148
|
+
*,
|
149
|
+
name: Optional[str] = None,
|
150
|
+
description: Optional[str] = None,
|
151
|
+
directives: Optional[Sequence[object]] = (),
|
152
|
+
include_computed: bool = False,
|
153
|
+
) -> type[BaseModel]: ...
|
154
|
+
|
155
|
+
|
156
|
+
@overload
|
157
|
+
def type(
|
158
|
+
*,
|
159
|
+
name: Optional[str] = None,
|
160
|
+
description: Optional[str] = None,
|
161
|
+
directives: Optional[Sequence[object]] = (),
|
162
|
+
include_computed: bool = False,
|
163
|
+
) -> Callable[[type[BaseModel]], type[BaseModel]]: ...
|
164
|
+
|
165
|
+
|
166
|
+
def type(
|
167
|
+
cls: Optional[type[BaseModel]] = None,
|
168
|
+
*,
|
169
|
+
name: Optional[str] = None,
|
170
|
+
description: Optional[str] = None,
|
171
|
+
directives: Optional[Sequence[object]] = (),
|
172
|
+
include_computed: bool = False,
|
173
|
+
) -> Union[type[BaseModel], Callable[[type[BaseModel]], type[BaseModel]]]:
|
174
|
+
"""Decorator to convert a Pydantic BaseModel directly into a GraphQL type.
|
175
|
+
|
176
|
+
This decorator allows you to use Pydantic models directly as GraphQL types
|
177
|
+
without needing to create a separate wrapper class.
|
178
|
+
|
179
|
+
Args:
|
180
|
+
cls: The Pydantic BaseModel class to convert
|
181
|
+
name: The GraphQL type name (defaults to class name)
|
182
|
+
description: The GraphQL type description
|
183
|
+
directives: GraphQL directives to apply to the type
|
184
|
+
include_computed: Whether to include computed fields
|
185
|
+
|
186
|
+
Returns:
|
187
|
+
The decorated BaseModel class with GraphQL metadata
|
188
|
+
|
189
|
+
Example:
|
190
|
+
@strawberry.pydantic.type
|
191
|
+
class User(BaseModel):
|
192
|
+
name: str
|
193
|
+
age: int
|
194
|
+
|
195
|
+
# All fields from the Pydantic model will be included in the GraphQL type
|
196
|
+
"""
|
197
|
+
|
198
|
+
def wrap(cls: type[BaseModel]) -> type[BaseModel]:
|
199
|
+
return _process_pydantic_type(
|
200
|
+
cls,
|
201
|
+
name=name,
|
202
|
+
is_input=False,
|
203
|
+
is_interface=False,
|
204
|
+
description=description,
|
205
|
+
directives=directives,
|
206
|
+
include_computed=include_computed,
|
207
|
+
)
|
208
|
+
|
209
|
+
if cls is None:
|
210
|
+
return wrap
|
211
|
+
|
212
|
+
return wrap(cls)
|
213
|
+
|
214
|
+
|
215
|
+
@overload
|
216
|
+
def input(
|
217
|
+
cls: type[BaseModel],
|
218
|
+
*,
|
219
|
+
name: Optional[str] = None,
|
220
|
+
description: Optional[str] = None,
|
221
|
+
directives: Optional[Sequence[object]] = (),
|
222
|
+
) -> type[BaseModel]: ...
|
223
|
+
|
224
|
+
|
225
|
+
@overload
|
226
|
+
def input(
|
227
|
+
*,
|
228
|
+
name: Optional[str] = None,
|
229
|
+
description: Optional[str] = None,
|
230
|
+
directives: Optional[Sequence[object]] = (),
|
231
|
+
) -> Callable[[type[BaseModel]], type[BaseModel]]: ...
|
232
|
+
|
233
|
+
|
234
|
+
def input(
|
235
|
+
cls: Optional[type[BaseModel]] = None,
|
236
|
+
*,
|
237
|
+
name: Optional[str] = None,
|
238
|
+
description: Optional[str] = None,
|
239
|
+
directives: Optional[Sequence[object]] = (),
|
240
|
+
) -> Union[type[BaseModel], Callable[[type[BaseModel]], type[BaseModel]]]:
|
241
|
+
"""Decorator to convert a Pydantic BaseModel directly into a GraphQL input type.
|
242
|
+
|
243
|
+
This decorator allows you to use Pydantic models directly as GraphQL input types
|
244
|
+
without needing to create a separate wrapper class.
|
245
|
+
|
246
|
+
Args:
|
247
|
+
cls: The Pydantic BaseModel class to convert
|
248
|
+
name: The GraphQL input type name (defaults to class name)
|
249
|
+
description: The GraphQL input type description
|
250
|
+
directives: GraphQL directives to apply to the input type
|
251
|
+
|
252
|
+
Returns:
|
253
|
+
The decorated BaseModel class with GraphQL input metadata
|
254
|
+
|
255
|
+
Example:
|
256
|
+
@strawberry.pydantic.input
|
257
|
+
class CreateUserInput(BaseModel):
|
258
|
+
name: str
|
259
|
+
age: int
|
260
|
+
|
261
|
+
# All fields from the Pydantic model will be included in the GraphQL input type
|
262
|
+
"""
|
263
|
+
|
264
|
+
def wrap(cls: type[BaseModel]) -> type[BaseModel]:
|
265
|
+
return _process_pydantic_type(
|
266
|
+
cls,
|
267
|
+
name=name,
|
268
|
+
is_input=True,
|
269
|
+
is_interface=False,
|
270
|
+
description=description,
|
271
|
+
directives=directives,
|
272
|
+
include_computed=False, # Input types don't need computed fields
|
273
|
+
)
|
274
|
+
|
275
|
+
if cls is None:
|
276
|
+
return wrap
|
277
|
+
|
278
|
+
return wrap(cls)
|
279
|
+
|
280
|
+
|
281
|
+
@overload
|
282
|
+
def interface(
|
283
|
+
cls: type[BaseModel],
|
284
|
+
*,
|
285
|
+
name: Optional[str] = None,
|
286
|
+
description: Optional[str] = None,
|
287
|
+
directives: Optional[Sequence[object]] = (),
|
288
|
+
include_computed: bool = False,
|
289
|
+
) -> type[BaseModel]: ...
|
290
|
+
|
291
|
+
|
292
|
+
@overload
|
293
|
+
def interface(
|
294
|
+
*,
|
295
|
+
name: Optional[str] = None,
|
296
|
+
description: Optional[str] = None,
|
297
|
+
directives: Optional[Sequence[object]] = (),
|
298
|
+
include_computed: bool = False,
|
299
|
+
) -> Callable[[type[BaseModel]], type[BaseModel]]: ...
|
300
|
+
|
301
|
+
|
302
|
+
def interface(
|
303
|
+
cls: Optional[type[BaseModel]] = None,
|
304
|
+
*,
|
305
|
+
name: Optional[str] = None,
|
306
|
+
description: Optional[str] = None,
|
307
|
+
directives: Optional[Sequence[object]] = (),
|
308
|
+
include_computed: bool = False,
|
309
|
+
) -> Union[type[BaseModel], Callable[[type[BaseModel]], type[BaseModel]]]:
|
310
|
+
"""Decorator to convert a Pydantic BaseModel directly into a GraphQL interface.
|
311
|
+
|
312
|
+
This decorator allows you to use Pydantic models directly as GraphQL interfaces
|
313
|
+
without needing to create a separate wrapper class.
|
314
|
+
|
315
|
+
Args:
|
316
|
+
cls: The Pydantic BaseModel class to convert
|
317
|
+
name: The GraphQL interface name (defaults to class name)
|
318
|
+
description: The GraphQL interface description
|
319
|
+
directives: GraphQL directives to apply to the interface
|
320
|
+
include_computed: Whether to include computed fields
|
321
|
+
|
322
|
+
Returns:
|
323
|
+
The decorated BaseModel class with GraphQL interface metadata
|
324
|
+
|
325
|
+
Example:
|
326
|
+
@strawberry.pydantic.interface
|
327
|
+
class Node(BaseModel):
|
328
|
+
id: str
|
329
|
+
"""
|
330
|
+
|
331
|
+
def wrap(cls: type[BaseModel]) -> type[BaseModel]:
|
332
|
+
return _process_pydantic_type(
|
333
|
+
cls,
|
334
|
+
name=name,
|
335
|
+
is_input=False,
|
336
|
+
is_interface=True,
|
337
|
+
description=description,
|
338
|
+
directives=directives,
|
339
|
+
include_computed=include_computed,
|
340
|
+
)
|
341
|
+
|
342
|
+
if cls is None:
|
343
|
+
return wrap
|
344
|
+
|
345
|
+
return wrap(cls)
|
346
|
+
|
347
|
+
|
348
|
+
__all__ = ["input", "interface", "type"]
|
{strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/RECORD
RENAMED
@@ -1,4 +1,4 @@
|
|
1
|
-
strawberry/__init__.py,sha256=
|
1
|
+
strawberry/__init__.py,sha256=55XU2lJuoy_VY9fGdV4T8DiSio1taskJBG4ukn62m44,1570
|
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
|
@@ -75,14 +75,14 @@ strawberry/exceptions/utils/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMp
|
|
75
75
|
strawberry/exceptions/utils/source_finder.py,sha256=wANz2bsXQW2TPES00XDWzDJsdnuAHcnjtM2_iv3eqsA,22566
|
76
76
|
strawberry/experimental/__init__.py,sha256=2HP5XtxL8ZKsPp4EDRAbMCqiP7p2V4Cca278JUGxnt0,102
|
77
77
|
strawberry/experimental/pydantic/__init__.py,sha256=UpO8wHNXGpoCYp34YStViInO1tsrGsMyhTVubTpJY7Y,255
|
78
|
-
strawberry/experimental/pydantic/_compat.py,sha256=
|
78
|
+
strawberry/experimental/pydantic/_compat.py,sha256=b8R_CirkeAuto8-5ZcTLzHonp8LSvuV5IkmQKEC9jzg,9709
|
79
79
|
strawberry/experimental/pydantic/conversion.py,sha256=xspWZtbCuhLeStf12X60c5cOrKp4ilVDlnW-tRU0_YY,4242
|
80
80
|
strawberry/experimental/pydantic/conversion_types.py,sha256=jf7PR5Q7hgo4J_AuxBK-BVj-8MC6vIg1k1pUfGfGTL8,925
|
81
|
-
strawberry/experimental/pydantic/error_type.py,sha256=
|
81
|
+
strawberry/experimental/pydantic/error_type.py,sha256=yn7F2kx0io1mK5PvQ-iAinR8HrL65voD-YAWGf9IjZY,4556
|
82
82
|
strawberry/experimental/pydantic/exceptions.py,sha256=pDMPL94ojuSGHxk8H8mI2pfWReG8BhqZ5T2eSxfOi9w,1486
|
83
|
-
strawberry/experimental/pydantic/fields.py,sha256=
|
83
|
+
strawberry/experimental/pydantic/fields.py,sha256=UEuhFfu2XTp2gNto6Di-Um2MZ6imo3e9chyoFobf4sM,2264
|
84
84
|
strawberry/experimental/pydantic/object_type.py,sha256=qoTQXO4qdno0M2oQv0sll7lqeyul_WDNmoSZpm5V14s,12863
|
85
|
-
strawberry/experimental/pydantic/utils.py,sha256=
|
85
|
+
strawberry/experimental/pydantic/utils.py,sha256=qlS8VJuS_9sv8o9Wj4LtjT5DhPrMs6bJIcHOvdEaXPI,4034
|
86
86
|
strawberry/ext/LICENSE,sha256=_oY0TZg0b_sW0--0T44aMTpy2e2zF1Kiyn8E1qDiivo,1249
|
87
87
|
strawberry/ext/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
88
88
|
strawberry/ext/dataclasses/LICENSE,sha256=WZgm35K_3NJwLqxpEHJJi7CWxVrwTumEz5D3Dtd7WnA,13925
|
@@ -152,6 +152,9 @@ strawberry/printer/__init__.py,sha256=DmepjmgtkdF5RxK_7yC6qUyRWn56U-9qeZMbkztYB9
|
|
152
152
|
strawberry/printer/ast_from_value.py,sha256=Tkme60qlykbN2m3dNPNMOe65X-wj6EmcDQwgQv7gUkc,4987
|
153
153
|
strawberry/printer/printer.py,sha256=5E9w0wDsUv1hvkeXof12277NLMiCVy5MgJ6gSo_NJhQ,19177
|
154
154
|
strawberry/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
155
|
+
strawberry/pydantic/__init__.py,sha256=1Z6_WtYpLGZR_Ev0indyL40EXFlNS3bqtonNRm2O9q8,558
|
156
|
+
strawberry/pydantic/fields.py,sha256=8oBY7Z-sTj6Tt3l9sNl1Wqk2ERxh-Doe2onQYnsGCP4,7188
|
157
|
+
strawberry/pydantic/object_type.py,sha256=sxFTE_VSpAcmOm7-EGL-tp0aobjoctOSjVQs34fRcD8,10785
|
155
158
|
strawberry/quart/__init__.py,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
156
159
|
strawberry/quart/views.py,sha256=bl9NKLS8731Vv2FYD1rky0gpKNbgMSTrscgduLh59R4,7514
|
157
160
|
strawberry/relay/__init__.py,sha256=Vi4btvA_g6Cj9Tk_F9GCSegapIf2WqkOWV8y3P0cTCs,553
|
@@ -236,8 +239,8 @@ strawberry/utils/logging.py,sha256=U1cseHGquN09YFhFmRkiphfASKCyK0HUZREImPgVb0c,7
|
|
236
239
|
strawberry/utils/operation.py,sha256=ZgVOw3K2jQuLjNOYUHauF7itJD0QDNoPw9PBi0IYf6k,1234
|
237
240
|
strawberry/utils/str_converters.py,sha256=-eH1Cl16IO_wrBlsGM-km4IY0IKsjhjnSNGRGOwQjVM,897
|
238
241
|
strawberry/utils/typing.py,sha256=SDvX-Du-9HAV3-XXjqi7Q5f5qPDDFd_gASIITiwBQT4,14073
|
239
|
-
strawberry_graphql-0.
|
240
|
-
strawberry_graphql-0.
|
241
|
-
strawberry_graphql-0.
|
242
|
-
strawberry_graphql-0.
|
243
|
-
strawberry_graphql-0.
|
242
|
+
strawberry_graphql-0.279.0.dev1754138688.dist-info/LICENSE,sha256=m-XnIVUKqlG_AWnfi9NReh9JfKhYOB-gJfKE45WM1W8,1072
|
243
|
+
strawberry_graphql-0.279.0.dev1754138688.dist-info/METADATA,sha256=JMWoCdEfWN1cM7Y5cOj95RNtcdAWpRjbLTwuJCy08VA,7407
|
244
|
+
strawberry_graphql-0.279.0.dev1754138688.dist-info/WHEEL,sha256=b4K_helf-jlQoXBBETfwnf4B04YC67LOev0jo4fX5m8,88
|
245
|
+
strawberry_graphql-0.279.0.dev1754138688.dist-info/entry_points.txt,sha256=Nk7-aT3_uEwCgyqtHESV9H6Mc31cK-VAvhnQNTzTb4k,49
|
246
|
+
strawberry_graphql-0.279.0.dev1754138688.dist-info/RECORD,,
|
{strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/LICENSE
RENAMED
File without changes
|
{strawberry_graphql-0.278.0.dist-info → strawberry_graphql-0.279.0.dev1754138688.dist-info}/WHEEL
RENAMED
File without changes
|
File without changes
|