CtrlK
BlogDocsLog inGet started
Tessl Logo

tessl/pypi-strawberry-graphql

A library for creating GraphQL APIs using dataclasses and type annotations with extensive framework integration support.

Overview
Eval results
Files

schema-execution.mddocs/

Schema and Execution

Schema creation and query execution system with support for queries, mutations, subscriptions, and context management. The Schema class is the central component that orchestrates GraphQL operation execution.

Capabilities

Schema Class

Main schema class for defining and executing GraphQL operations.

class Schema:
    """Main GraphQL schema class for executing queries, mutations, and subscriptions."""
    
    def __init__(
        self,
        query: Type = None,
        mutation: Type = None,
        subscription: Type = None,
        *,
        types: List[Type] = None,
        extensions: List[SchemaExtension] = None,
        execution_context_class: Type = None,
        introspection: bool = True,
        auto_camel_case: bool = True
    ):
        """
        Initialize a GraphQL schema.
        
        Args:
            query: Root query type
            mutation: Root mutation type (optional)
            subscription: Root subscription type (optional)
            types: Additional types to include in schema
            extensions: Schema extensions for custom functionality
            execution_context_class: Custom execution context class
            introspection: Whether to enable introspection
            auto_camel_case: Whether to auto-convert field names to camelCase
        """
    
    # Schema properties
    query_type: Type  # Root query type
    mutation_type: Optional[Type]  # Root mutation type
    subscription_type: Optional[Type]  # Root subscription type
    types: List[Type]  # All types in the schema

Usage Example:

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

@strawberry.type
class Mutation:
    @strawberry.mutation
    def create_user(self, name: str) -> User:
        return User(id="1", name=name)

@strawberry.type
class Subscription:
    @strawberry.subscription
    async def user_updates(self) -> AsyncIterator[User]:
        # Subscription logic here
        yield User(id="1", name="Alice")

# Create schema
schema = strawberry.Schema(
    query=Query,
    mutation=Mutation,
    subscription=Subscription,
    extensions=[
        QueryDepthLimiter(max_depth=10),
        ValidationCache()
    ]
)

Synchronous Execution

Execute GraphQL queries synchronously.

def execute_sync(
    self,
    query: str,
    variable_values: Dict[str, Any] = None,
    context_value: Any = None,
    root_value: Any = None,
    operation_name: str = None
) -> ExecutionResult:
    """
    Execute a GraphQL query synchronously.
    
    Args:
        query: GraphQL query string
        variable_values: Variables for the query
        context_value: Context passed to resolvers
        root_value: Root value for top-level resolvers
        operation_name: Name of operation to execute (for multi-operation queries)
    
    Returns:
        ExecutionResult with data and errors
    """

Usage Example:

# Simple query execution
result = schema.execute_sync("""
    query {
        hello
    }
""")

print(result.data)  # {'hello': 'Hello, World!'}

# Query with variables
result = schema.execute_sync(
    """
    query GetUser($id: ID!) {
        user(id: $id) {
            name
            email
        }
    }
    """,
    variable_values={"id": "123"}
)

# Query with context
class Context:
    def __init__(self, user=None):
        self.user = user

result = schema.execute_sync(
    """
    query {
        currentUser {
            name
        }
    }
    """,
    context_value=Context(user=current_user)
)

Asynchronous Execution

Execute GraphQL queries asynchronously for better performance with async resolvers.

async def execute(
    self,
    query: str,
    variable_values: Dict[str, Any] = None,
    context_value: Any = None,
    root_value: Any = None,
    operation_name: str = None
) -> ExecutionResult:
    """
    Execute a GraphQL query asynchronously.
    
    Args:
        query: GraphQL query string
        variable_values: Variables for the query
        context_value: Context passed to resolvers
        root_value: Root value for top-level resolvers
        operation_name: Name of operation to execute
    
    Returns:
        ExecutionResult with data and errors
    """

Usage Example:

import asyncio

async def main():
    # Async query execution
    result = await schema.execute("""
        query {
            users {
                id
                name
                posts {
                    title
                }
            }
        }
    """)
    
    if result.errors:
        print("Errors:", result.errors)
    else:
        print("Data:", result.data)

# Run async execution
asyncio.run(main())

Subscription Execution

Execute GraphQL subscriptions for real-time data streaming.

async def subscribe(
    self,
    query: str,
    variable_values: Dict[str, Any] = None,
    context_value: Any = None,
    root_value: Any = None,
    operation_name: str = None
) -> AsyncIterator[ExecutionResult]:
    """
    Execute a GraphQL subscription.
    
    Args:
        query: GraphQL subscription string
        variable_values: Variables for the subscription
        context_value: Context passed to resolvers
        root_value: Root value for top-level resolvers
        operation_name: Name of operation to execute
    
    Yields:
        ExecutionResult for each subscription event
    """

Usage Example:

async def handle_subscription():
    subscription_query = """
        subscription {
            messageUpdates(roomId: "123") {
                id
                content
                author {
                    name
                }
                timestamp
            }
        }
    """
    
    async for result in schema.subscribe(subscription_query):
        if result.errors:
            print("Subscription error:", result.errors)
        else:
            message = result.data["messageUpdates"]
            print(f"New message: {message['content']} from {message['author']['name']}")

Execution Results

ExecutionResult

Result object returned by query and mutation execution.

class ExecutionResult:
    """Result of GraphQL query or mutation execution."""
    
    data: Optional[Dict[str, Any]]  # Query result data
    errors: Optional[List[GraphQLError]]  # Execution errors
    extensions: Optional[Dict[str, Any]]  # Extension data

Usage Example:

result = schema.execute_sync("""
    query {
        user(id: "invalid") {
            name
        }
    }
""")

if result.errors:
    for error in result.errors:
        print(f"Error: {error.message}")
        print(f"Path: {error.path}")
        print(f"Locations: {error.locations}")
else:
    print(f"Data: {result.data}")

# Access extensions (from schema extensions)
if result.extensions:
    print(f"Query complexity: {result.extensions.get('complexity')}")
    print(f"Execution time: {result.extensions.get('execution_time')}")

SubscriptionExecutionResult

Result object for subscription execution with async iteration support.

class SubscriptionExecutionResult:
    """Result of GraphQL subscription execution."""
    
    def __aiter__(self) -> AsyncIterator[ExecutionResult]:
        """Async iterator for subscription results."""
    
    async def __anext__(self) -> ExecutionResult:
        """Get next subscription result."""

Execution Context

ExecutionContext

Context object that manages the execution of a GraphQL operation.

class ExecutionContext:
    """Context for GraphQL operation execution."""
    
    schema: Schema  # GraphQL schema
    document: DocumentNode  # Parsed GraphQL document
    root_value: Any  # Root value for resolvers
    context_value: Any  # Context passed to resolvers
    variable_values: Dict[str, Any]  # Operation variables
    operation_name: Optional[str]  # Name of operation being executed
    field_resolver: Callable  # Field resolver function
    type_resolver: Callable  # Type resolver function
    subscribe_field_resolver: Callable  # Subscription field resolver

Advanced Schema Configuration

Custom Types Registration

# Register additional types that might not be directly referenced
@strawberry.type
class AdminUser:
    id: strawberry.ID
    name: str
    admin_level: int

schema = strawberry.Schema(
    query=Query,
    types=[AdminUser]  # Ensure AdminUser is included in schema
)

Schema Introspection Control

# Disable introspection for production
production_schema = strawberry.Schema(
    query=Query,
    introspection=False  # Disable introspection queries
)

# Or use extension
from strawberry.extensions import DisableIntrospection

schema = strawberry.Schema(
    query=Query,
    extensions=[DisableIntrospection()]
)

Custom Field Name Conversion

# Disable automatic camelCase conversion
schema = strawberry.Schema(
    query=Query,
    auto_camel_case=False  # Keep original Python field names
)

@strawberry.type
class User:
    user_id: strawberry.ID  # Will remain as 'user_id' in GraphQL
    first_name: str  # Will remain as 'first_name' in GraphQL

Error Handling

class CustomError(Exception):
    """Custom application error."""
    def __init__(self, message: str, code: str = None):
        self.message = message
        self.code = code
        super().__init__(message)

@strawberry.type
class Query:
    @strawberry.field
    def risky_operation(self) -> str:
        try:
            return perform_risky_operation()
        except CustomError as e:
            # Errors are automatically added to the result
            raise e
        except Exception as e:
            # Generic error handling
            raise GraphQLError(f"Operation failed: {str(e)}")

# Execute with error handling
result = schema.execute_sync("""
    query {
        riskyOperation
    }
""")

if result.errors:
    for error in result.errors:
        print(f"Error: {error.message}")
        if hasattr(error.original_error, 'code'):
            print(f"Code: {error.original_error.code}")

Schema Printing

from strawberry.printer import print_schema

# Print schema SDL (Schema Definition Language)
sdl = print_schema(schema)
print(sdl)

Example Output:

type Query {
  hello: String!
  user(id: ID!): User
}

type User {
  id: ID!
  name: String!
  email: String!
}

type Mutation {
  createUser(name: String!): User!
}

Multi-Operation Queries

# Execute specific operation from multi-operation query
multi_operation_query = """
    query GetUsers {
        users { id name }
    }
    
    query GetPosts {
        posts { id title }
    }
"""

# Execute specific operation
result = schema.execute_sync(
    multi_operation_query,
    operation_name="GetUsers"
)

Install with Tessl CLI

npx tessl i tessl/pypi-strawberry-graphql

docs

core-types.md

experimental.md

extensions.md

federation.md

fields-resolvers.md

framework-integrations.md

index.md

relay.md

schema-execution.md

utilities.md

tile.json