or run

npx @tessl/cli init
Log in

Version

Tile

Overview

Evals

Files

Files

docs

index.mdrelay.mdschema-execution.mdtype-system.md

type-system.mddocs/

0

# Type System

1

2

Graphene provides a comprehensive GraphQL type system through Python classes that mirror the GraphQL specification. This includes object types for data structures, scalar types for primitive values, composite types for complex relationships, input types for mutations and queries, and field definitions for connecting data.

3

4

## Capabilities

5

6

### Object Types

7

8

Define GraphQL object types that represent data structures with typed fields and resolvers.

9

10

```python { .api }

11

class ObjectType(BaseType):

12

"""

13

Primary GraphQL object type for defining data structures.

14

15

Features:

16

- Automatic dataclass integration for field access

17

- Field collection via metaclass

18

- Interface implementation support

19

- Custom resolver binding

20

21

Meta Options:

22

interfaces: List of interfaces this type implements

23

possible_types: For interface resolution

24

default_resolver: Default field resolver function

25

fields: Custom field definitions

26

27

Usage:

28

class Person(graphene.ObjectType):

29

name = graphene.String(required=True)

30

age = graphene.Int()

31

32

def resolve_age(self, info):

33

return self.calculate_age()

34

"""

35

```

36

37

### Field Definitions

38

39

Define individual fields on GraphQL types with arguments, resolvers, and metadata.

40

41

```python { .api }

42

class Field(MountedType):

43

"""

44

Defines individual fields on GraphQL types.

45

46

Parameters:

47

type_: The GraphQL type for this field

48

args: Dictionary of field arguments

49

resolver: Custom resolver function

50

source: Source field name for automatic resolution

51

deprecation_reason: Deprecation message

52

name: Field name (defaults to Python attribute name)

53

description: Field description

54

required: Whether field is NonNull (alternative to NonNull wrapper)

55

default_value: Default value for the field

56

57

Methods:

58

wrap_resolve(parent_resolver): Wraps resolver for field resolution

59

wrap_subscribe(parent_subscribe): Wraps subscription resolver

60

"""

61

62

def Field(type_, **kwargs):

63

"""

64

Create a field with the specified type and options.

65

66

Args:

67

type_: GraphQL type (String, Int, ObjectType, etc.)

68

resolver: Custom resolver function

69

args: Field arguments

70

required: Make field non-null

71

description: Field documentation

72

deprecation_reason: Mark field as deprecated

73

74

Returns:

75

Field instance

76

"""

77

```

78

79

### Scalar Types

80

81

Built-in GraphQL scalar types for primitive values with automatic serialization and parsing.

82

83

#### Basic Scalars

84

85

```python { .api }

86

class String(Scalar):

87

"""

88

UTF-8 text representation with automatic type coercion.

89

90

Features:

91

- Coerces various Python types to string

92

- UTF-8 encoding/decoding

93

- Null value handling

94

"""

95

96

class Int(Scalar):

97

"""

98

32-bit signed integers with range validation.

99

100

Range: -2^31 to 2^31-1

101

Features:

102

- Automatic range checking

103

- Float to int conversion with validation

104

- Null value handling

105

"""

106

107

class BigInt(Scalar):

108

"""

109

Unlimited precision integers.

110

111

Features:

112

- No range limitations

113

- Handles Python's arbitrary precision integers

114

- String/numeric parsing

115

"""

116

117

class Float(Scalar):

118

"""

119

IEEE 754 double-precision floating point numbers.

120

121

Features:

122

- Standard floating point operations

123

- Automatic type coercion from int/string

124

- NaN and infinity handling

125

"""

126

127

class Boolean(Scalar):

128

"""

129

True/false values with Python truthiness conversion.

130

131

Features:

132

- Uses Python's bool() function for coercion

133

- Handles various truthy/falsy values

134

"""

135

136

class ID(Scalar):

137

"""

138

Unique identifier that accepts string or int, serializes to string.

139

140

Features:

141

- Accepts both string and integer input

142

- Always serializes to string format

143

- Used for object identification

144

"""

145

```

146

147

#### Extended Scalars

148

149

```python { .api }

150

class UUID(Scalar):

151

"""

152

Native UUID type using Python's uuid.UUID.

153

154

Features:

155

- Automatic UUID validation

156

- String to UUID conversion

157

- Standard UUID format support

158

"""

159

160

class DateTime(Scalar):

161

"""

162

ISO 8601 datetime representation with timezone support.

163

164

Features:

165

- Uses dateutil.parser.isoparse for flexible parsing

166

- Timezone-aware datetime support

167

- ISO 8601 string serialization

168

"""

169

170

class Date(Scalar):

171

"""

172

ISO 8601 date representation (YYYY-MM-DD).

173

174

Features:

175

- Handles datetime.date objects

176

- ISO date string parsing

177

- Date-only operations

178

"""

179

180

class Time(Scalar):

181

"""

182

ISO 8601 time representation (HH:MM:SS).

183

184

Features:

185

- Handles datetime.time objects

186

- Time-only operations

187

- Optional microsecond precision

188

"""

189

190

class Decimal(Scalar):

191

"""

192

Python Decimal type for precise numeric values.

193

194

Features:

195

- Maintains decimal precision

196

- String/numeric parsing

197

- Financial calculations support

198

"""

199

200

class JSONString(Scalar):

201

"""

202

JSON-encoded strings (not recommended for schema design).

203

204

Warning: Not recommended for new schemas

205

Features:

206

- Automatic JSON serialization/deserialization

207

- Bypasses GraphQL type system

208

"""

209

210

class Base64(Scalar):

211

"""

212

Base64-encoded binary data.

213

214

Features:

215

- Automatic base64 encoding/decoding

216

- UTF-8 string handling

217

- Binary data transport

218

"""

219

```

220

221

### Composite Types

222

223

Complex GraphQL types for representing relationships and polymorphism.

224

225

```python { .api }

226

class Interface(BaseType):

227

"""

228

Defines shared fields across multiple object types.

229

230

Features:

231

- Field inheritance for implementing types

232

- Type resolution at query time

233

- Cannot be instantiated directly

234

235

Meta Options:

236

fields: Field definitions

237

interfaces: Other interfaces this extends

238

239

Methods:

240

resolve_type(instance, info): Determines concrete type from instance

241

242

Usage:

243

class Node(graphene.Interface):

244

id = graphene.ID(required=True)

245

246

@classmethod

247

def resolve_type(cls, instance, info):

248

return type(instance).__name__

249

"""

250

251

class Union(UnmountedType, BaseType):

252

"""

253

Represents one of several possible object types.

254

255

Features:

256

- Type resolution at query time

257

- No shared fields between types

258

- Useful for search results or heterogeneous collections

259

260

Meta Options:

261

types: Required list of ObjectTypes in the union

262

263

Methods:

264

resolve_type(instance, info): Type resolution for union members

265

266

Usage:

267

class SearchResult(graphene.Union):

268

class Meta:

269

types = (Person, Company, Product)

270

"""

271

272

class Enum(EnumMeta):

273

"""

274

Defines static set of named values.

275

276

Features:

277

- Automatic Python Enum integration

278

- Custom equality/hashing for enum values

279

- Dynamic enum creation

280

281

Meta Options:

282

enum: Python Enum class to use

283

description: Enum description

284

deprecation_reason: Mark enum as deprecated

285

286

Class Methods:

287

from_enum(python_enum): Create GraphQL enum from Python enum

288

289

Usage:

290

class Color(graphene.Enum):

291

RED = 1

292

GREEN = 2

293

BLUE = 3

294

295

# Or from Python enum

296

from enum import Enum as PyEnum

297

class Status(PyEnum):

298

ACTIVE = "active"

299

INACTIVE = "inactive"

300

301

GraphQLStatus = graphene.Enum.from_enum(Status)

302

"""

303

```

304

305

### Input Types

306

307

Types for accepting structured input data in mutations and query arguments.

308

309

```python { .api }

310

class InputObjectType(UnmountedType, BaseType):

311

"""

312

Structured input data for mutations and queries.

313

314

Features:

315

- Automatic InputField mounting

316

- Container class generation for value objects

317

- Default value handling

318

- Validation support

319

320

Meta Options:

321

container: Custom container class for input values

322

fields: Custom field definitions

323

324

Usage:

325

class PersonInput(graphene.InputObjectType):

326

name = graphene.String(required=True)

327

age = graphene.Int()

328

email = graphene.String()

329

"""

330

331

class InputField(MountedType):

332

"""

333

Individual input fields on InputObjectType.

334

335

Parameters:

336

type_: Input field type (no Interface/Union types allowed)

337

name: Field name

338

default_value: Default value for optional fields

339

deprecation_reason: Deprecation message

340

description: Field description

341

required: Whether field is NonNull

342

343

Restrictions:

344

- No arguments (unlike regular Field)

345

- Cannot use Interface or Union types

346

- Only input types allowed

347

348

Usage:

349

email = graphene.InputField(

350

graphene.String,

351

description="User email address",

352

required=True

353

)

354

"""

355

356

class Argument(MountedType):

357

"""

358

Field arguments for queries and mutations.

359

360

Parameters:

361

type_: Argument type

362

default_value: Default value for optional arguments

363

deprecation_reason: Deprecation message

364

description: Argument description

365

name: Argument name

366

required: Whether argument is NonNull

367

368

Features:

369

- Automatic conversion from UnmountedTypes

370

- Argument validation

371

- Default value handling

372

373

Usage:

374

def resolve_users(self, info, limit=graphene.Argument(graphene.Int, default_value=10)):

375

return User.objects.all()[:limit]

376

"""

377

```

378

379

### Structure Modifiers

380

381

Wrappers for modifying type nullability and creating lists.

382

383

```python { .api }

384

class List(Structure):

385

"""

386

Array/list type wrapper for GraphQL lists.

387

388

Features:

389

- Type-safe list operations

390

- Nested list support

391

- Null item handling

392

393

Usage:

394

users = graphene.List(User) # [User]

395

matrix = graphene.List(graphene.List(graphene.Int)) # [[Int]]

396

"""

397

398

class NonNull(Structure):

399

"""

400

Non-nullable type wrapper for required fields.

401

402

Features:

403

- Prevents null values

404

- Validation at execution time

405

- Cannot be nested (NonNull(NonNull(T)) is invalid)

406

407

Usage:

408

name = graphene.NonNull(graphene.String) # String!

409

# Or use required=True

410

name = graphene.String(required=True)

411

"""

412

```

413

414

### Special Types

415

416

Advanced types for complex scenarios and runtime behavior.

417

418

```python { .api }

419

class Dynamic(MountedType):

420

"""

421

Runtime type resolution for lazy fields and circular references.

422

423

Parameters:

424

type_: Function that returns the actual type

425

with_schema: Whether to pass schema to type function

426

427

Methods:

428

get_type(schema=None): Resolves type at schema build time

429

430

Usage:

431

# Resolve circular reference

432

def get_user_type():

433

return User

434

435

friends = graphene.Dynamic(get_user_type)

436

437

# With schema access

438

def get_type_with_schema(schema):

439

return schema.get_type('User')

440

441

user = graphene.Dynamic(get_type_with_schema, with_schema=True)

442

"""

443

444

class Scalar(GraphQLScalar):

445

"""

446

Base class for custom scalar types.

447

448

Abstract Methods:

449

serialize(value): Convert internal value to transport format

450

parse_value(value): Parse transport value to internal format

451

parse_literal(ast_node): Parse AST literal to internal format

452

453

Usage:

454

class EmailScalar(graphene.Scalar):

455

@staticmethod

456

def serialize(email):

457

return str(email)

458

459

@staticmethod

460

def parse_value(value):

461

if not re.match(r'^[^@]+@[^@]+\.[^@]+$', value):

462

raise ValueError('Invalid email format')

463

return value

464

465

@staticmethod

466

def parse_literal(node):

467

if isinstance(node, StringValueNode):

468

return EmailScalar.parse_value(node.value)

469

raise ValueError('Expected string value')

470

"""

471

```

472

473

## Usage Examples

474

475

### Creating Custom Object Types

476

477

```python

478

import graphene

479

480

class Address(graphene.ObjectType):

481

street = graphene.String(required=True)

482

city = graphene.String(required=True)

483

country = graphene.String(required=True)

484

postal_code = graphene.String()

485

486

class Person(graphene.ObjectType):

487

# Basic fields

488

name = graphene.String(required=True, description="Full name")

489

age = graphene.Int(description="Age in years")

490

email = graphene.String()

491

492

# Complex fields

493

address = graphene.Field(Address)

494

friends = graphene.List(lambda: Person) # Self-reference

495

496

# Field with arguments

497

posts = graphene.List(

498

'Post', # String reference to avoid circular import

499

limit=graphene.Argument(graphene.Int, default_value=10)

500

)

501

502

# Custom resolver

503

def resolve_posts(self, info, limit=10):

504

return get_posts_for_user(self.id, limit)

505

506

# Computed field

507

display_name = graphene.String()

508

509

def resolve_display_name(self, info):

510

return f"{self.name} ({self.age})"

511

```

512

513

### Working with Input Types

514

515

```python

516

class CreatePersonInput(graphene.InputObjectType):

517

name = graphene.String(required=True)

518

age = graphene.Int()

519

email = graphene.String()

520

address = graphene.Field('AddressInput')

521

522

class AddressInput(graphene.InputObjectType):

523

street = graphene.String(required=True)

524

city = graphene.String(required=True)

525

country = graphene.String(required=True)

526

postal_code = graphene.String()

527

528

class CreatePerson(graphene.Mutation):

529

class Arguments:

530

input = CreatePersonInput(required=True)

531

532

person = graphene.Field(Person)

533

success = graphene.Boolean()

534

535

def mutate(self, info, input):

536

# Access input fields

537

person_data = {

538

'name': input.name,

539

'age': input.age,

540

'email': input.email

541

}

542

543

if input.address:

544

person_data['address'] = {

545

'street': input.address.street,

546

'city': input.address.city,

547

'country': input.address.country,

548

'postal_code': input.address.postal_code

549

}

550

551

# Create person

552

person = create_person(person_data)

553

return CreatePerson(person=person, success=True)

554

```

555

556

### Custom Scalar Example

557

558

```python

559

import graphene

560

import re

561

from datetime import datetime

562

from graphql.language.ast import StringValueNode

563

564

class EmailType(graphene.Scalar):

565

"""Email address scalar with validation."""

566

567

@staticmethod

568

def serialize(email):

569

"""Serialize email to string."""

570

return str(email)

571

572

@staticmethod

573

def parse_value(value):

574

"""Parse email from input value."""

575

if not isinstance(value, str):

576

raise ValueError(f"Expected string, got {type(value).__name__}")

577

578

email_pattern = r'^[a-zA-Z0-9._%+-]+@[a-zA-Z0-9.-]+\.[a-zA-Z]{2,}$'

579

if not re.match(email_pattern, value):

580

raise ValueError(f"Invalid email format: {value}")

581

582

return value

583

584

@staticmethod

585

def parse_literal(node):

586

"""Parse email from AST literal."""

587

if isinstance(node, StringValueNode):

588

return EmailType.parse_value(node.value)

589

raise ValueError("Expected string literal for email")

590

591

# Usage in schema

592

class User(graphene.ObjectType):

593

name = graphene.String()

594

email = EmailType() # Custom scalar

595

verified_at = graphene.DateTime()

596

```