File: schema.md

package info (click to toggle)
strawberry-graphql 0.306.0-1
  • links: PTS, VCS
  • area: main
  • in suites: sid
  • size: 18,176 kB
  • sloc: javascript: 178,052; python: 65,643; sh: 33; makefile: 25
file content (311 lines) | stat: -rw-r--r-- 7,208 bytes parent folder | download
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
---
title: Schema
---

# Schema

Every GraphQL API has a schema and that is used to define all the
functionalities for an API. A schema is defined by passing 3
[object types](./object-types): `Query`, `Mutation` and `Subscription`.

`Mutation` and `Subscription` are optional, meanwhile `Query` has to always be
there.

This is an example of a schema defined using Strawberry:

```python
import strawberry


@strawberry.type
class Query:
    @strawberry.field
    def hello(self) -> str:
        return "Hello World"


schema = strawberry.Schema(Query)
```

## API reference

```python
class Schema(Query, mutation=None, subscription=None, **kwargs): ...
```

<!-- TODO: add docs on directives, types, extensions and execution context class -->

#### `query: Type`

The root query Strawberry type. Usually called `Query`.

<Note>

A query type is always required when creating a Schema.

</Note>

#### `mutation: Optional[Type] = None`

The root mutation type. Usually called `Mutation`.

#### `subscription: Optional[Type] = None`

The root subscription type. Usually called `Subscription`.

#### `config: Optional[StrawberryConfig] = None`

Pass a `StrawberryConfig` object to configure how the schema is generated.
[Read more](/docs/types/schema-configurations).

#### `types: List[Type] = []`

List of extra types to register with the Schema that are not directly linked to
from the root Query.

<details class="mb-4">
<summary>Defining extra `types` when using Interfaces</summary>

```python
from datetime import date
import strawberry


@strawberry.interface
class Customer:
    name: str


@strawberry.type
class Individual(Customer):
    date_of_birth: date


@strawberry.type
class Company(Customer):
    founded: date


@strawberry.type
class Query:
    @strawberry.field
    def get_customer(
        self, id: strawberry.ID
    ) -> Customer:  # note we're returning the interface here
        if id == "mark":
            return Individual(name="Mark", date_of_birth=date(1984, 5, 14))

        if id == "facebook":
            return Company(name="Facebook", founded=date(2004, 2, 1))


schema = strawberry.Schema(Query, types=[Individual, Company])
```

</details>

#### `extensions: List[Type[SchemaExtension]] = []`

List of [extensions](/docs/extensions) to add to your Schema.

#### `scalar_overrides: Optional[Dict[object, ScalarWrapper]] = None`

Override the implementation of the built in scalars.
[More information](/docs/types/scalars#overriding-built-in-scalars).

---

## Methods

### `.execute()` (async)

Executes a GraphQL operation against a schema (async)

```python
async def execute(
    query, variable_values, context_value, root_value, operation_name
): ...
```

#### `query: str`

The GraphQL document to be executed.

#### `variable_values: Optional[Dict[str, Any]] = None`

The variables for this operation.

#### `context_value: Optional[Any] = None`

The value of the context that will be passed down to resolvers.

#### `root_value: Optional[Any] = None`

The value for the root value that will passed to root resolvers.

#### `operation_name: Optional[str] = None`

The name of the operation you want to execute, useful when sending a document
with multiple operations. If no `operation_name` is specified the first
operation in the document will be executed.

### `.execute_sync()`

Executes a GraphQL operation against a schema

```python
def execute_sync(query, variable_values, context_value, root_value, operation_name): ...
```

#### `query: str`

The GraphQL document to be executed.

#### `variable_values: Optional[Dict[str, Any]] = None`

The variables for this operation.

#### `context_value: Optional[Any] = None`

The value of the context that will be passed down to resolvers.

#### `root_value: Optional[Any] = None`

The value for the root value that will passed to root resolvers.

#### `operation_name: Optional[str] = None`

The name of the operation you want to execute, useful when sending a document
with multiple operations. If no `operation_name` is specified the first
operation in the document will be executed.

---

## Handling execution errors

By default Strawberry will log any errors encountered during a query execution
to a `strawberry.execution` logger. This behaviour can be changed by overriding
the `process_errors` function on the `strawberry.Schema` class.

The default functionality looks like this:

```python
# strawberry/schema/base.py
from strawberry.types import ExecutionContext

logger = logging.getLogger("strawberry.execution")


class BaseSchema:
    ...

    def process_errors(
        self,
        errors: List[GraphQLError],
        execution_context: Optional[ExecutionContext] = None,
    ) -> None:
        for error in errors:
            StrawberryLogger.error(error, execution_context)
```

```python
# strawberry/utils/logging.py
from strawberry.types import ExecutionContext


class StrawberryLogger:
    logger: Final[logging.Logger] = logging.getLogger("strawberry.execution")

    @classmethod
    def error(
        cls,
        error: GraphQLError,
        execution_context: Optional[ExecutionContext] = None,
        # https://www.python.org/dev/peps/pep-0484/#arbitrary-argument-lists-and-default-argument-values
        **logger_kwargs: Any,
    ) -> None:
        # "stack_info" is a boolean; check for None explicitly
        if logger_kwargs.get("stack_info") is None:
            logger_kwargs["stack_info"] = True

        logger_kwargs["stacklevel"] = 3

        cls.logger.error(error, exc_info=error.original_error, **logger_kwargs)
```

## Filtering/customising fields

You can customise the fields that are exposed on a schema by subclassing the
`Schema` class and overriding the `get_fields` method, for example you can use
this to create different GraphQL APIs, such as a public and an internal API.
Here's an example of this:

```python
@strawberry.type
class User:
    name: str
    email: str = strawberry.field(metadata={"tags": ["internal"]})


@strawberry.type
class Query:
    user: User


def public_field_filter(field: StrawberryField) -> bool:
    return "internal" not in field.metadata.get("tags", [])


class PublicSchema(strawberry.Schema):
    def get_fields(
        self, type_definition: StrawberryObjectDefinition
    ) -> List[StrawberryField]:
        return list(filter(public_field_filter, type_definition.fields))


schema = PublicSchema(query=Query)
```

<Note>

The `get_fields` method is only called once when creating the schema, this is
not intended to be used to dynamically customise the schema.

</Note>

## Deprecating fields

Fields can be deprecated using the argument `deprecation_reason`.

<Note>

This does not prevent the field from being used, it's only for documentation.
See:
[GraphQL field deprecation](https://spec.graphql.org/June2018/#sec-Field-Deprecation).

</Note>

<CodeGrid>

```python
import strawberry
import datetime
from typing import Optional


@strawberry.type
class User:
    name: str
    dob: datetime.date
    age: Optional[int] = strawberry.field(deprecation_reason="Age is deprecated")
```

```graphql
type User {
  name: String!
  dob: Date!
  age: Int @deprecated(reason: "Age is deprecated")
}
```

</CodeGrid>