diff --git a/test-strawberry/.gitignore b/test-strawberry/.gitignore new file mode 100644 index 0000000..e74dcbf --- /dev/null +++ b/test-strawberry/.gitignore @@ -0,0 +1,2 @@ +.venv/ +uv.lock diff --git a/test-strawberry/.python-version b/test-strawberry/.python-version new file mode 100644 index 0000000..6324d40 --- /dev/null +++ b/test-strawberry/.python-version @@ -0,0 +1 @@ +3.14 diff --git a/test-strawberry/main.py b/test-strawberry/main.py new file mode 100644 index 0000000..7e985d1 --- /dev/null +++ b/test-strawberry/main.py @@ -0,0 +1,107 @@ +import asyncio +import os +from typing import AsyncGenerator + +import sentry_sdk +import strawberry +from fastapi import FastAPI +from sentry_sdk.integrations.strawberry import StrawberryIntegration +from strawberry.fastapi import GraphQLRouter + +sentry_sdk.init( + dsn=os.environ.get("SENTRY_DSN"), + environment=os.environ.get("ENV", "test"), + traces_sample_rate=1.0, + profiles_sample_rate=1.0, + debug=True, + integrations=[ + StrawberryIntegration(async_execution=True), + ], + _experiments={"trace_lifecycle": "stream"}, +) + + +@strawberry.type +class Book: + title: str + author: str + year: int + + +books_db: list[Book] = [ + Book(title="Oryx and Crake", author="Margaret Atwood", year=2003), + Book(title="I, Robot", author="Isaac Asimov", year=1950), + Book(title="A Closed and Common Orbit", author="Becky Chambers", year=2016), +] + + +@strawberry.type +class AddBookResult: + success: bool + book: Book + + +@strawberry.type +class Query: + @strawberry.field + def hello(self) -> str: + return "Hello from Strawberry GraphQL!" + + @strawberry.field + def books(self) -> list[Book]: + return books_db + + @strawberry.field + def book_by_title(self, title: str) -> Book: + for book in books_db: + if book.title.lower() == title.lower(): + return book + raise ValueError(f"Book not found: {title}") + + @strawberry.field + def error(self) -> str: + raise ValueError("help! an error!") + + +@strawberry.type +class Mutation: + @strawberry.mutation + def add_book(self, title: str, author: str, year: int) -> AddBookResult: + book = Book(title=title, author=author, year=year) + books_db.append(book) + return AddBookResult(success=True, book=book) + + @strawberry.mutation + def delete_all_books(self) -> bool: + books_db.clear() + return True + + @strawberry.mutation + def mutation_error(self) -> str: + raise RuntimeError("mutation failed!") + + +@strawberry.type +class Subscription: + @strawberry.subscription + async def countdown(self, start: int = 5) -> AsyncGenerator[int, None]: + for i in range(start, 0, -1): + yield i + await asyncio.sleep(1) + + @strawberry.subscription + async def subscription_error(self) -> AsyncGenerator[str, None]: + yield "starting..." + raise RuntimeError("subscription exploded!") + + +schema = strawberry.Schema( + query=Query, + mutation=Mutation, + subscription=Subscription, +) + +graphql_app = GraphQLRouter(schema) + +app = FastAPI() +app.include_router(graphql_app, prefix="/graphql") diff --git a/test-strawberry/pyproject.toml b/test-strawberry/pyproject.toml new file mode 100644 index 0000000..de4aa67 --- /dev/null +++ b/test-strawberry/pyproject.toml @@ -0,0 +1,15 @@ +[project] +name = "test-strawberry" +version = "0" +requires-python = ">=3.12" + +dependencies = [ + "fastapi>=0.115.11", + "ipdb>=0.13.13", + "sentry-sdk[strawberry]", + "strawberry-graphql[fastapi]>=0.243.0", + "uvicorn>=0.34.0", +] + +[tool.uv.sources] +sentry-sdk = { path = "../../sentry-python", editable = true } diff --git a/test-strawberry/run.sh b/test-strawberry/run.sh new file mode 100755 index 0000000..8d04e49 --- /dev/null +++ b/test-strawberry/run.sh @@ -0,0 +1,12 @@ +#!/usr/bin/env bash + +# exit on first error +set -euo pipefail + +# Install uv if it's not installed +if ! command -v uv &> /dev/null; then + curl -LsSf https://astral.sh/uv/install.sh | sh +fi + +# Run the script +uv run uvicorn main:app --port 8000 --reload