Skip to content

Commit

Permalink
Super wip
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick91 committed Jan 22, 2025
1 parent 8c40f5a commit eb43d5e
Show file tree
Hide file tree
Showing 5 changed files with 96 additions and 44 deletions.
19 changes: 15 additions & 4 deletions strawberry/http/async_base_view.py
Original file line number Diff line number Diff line change
Expand Up @@ -358,9 +358,7 @@ async def run(
except MissingQueryError as e:
raise HTTPException(400, "No GraphQL query found in the request") from e

if HAS_INCREMENTAL_EXECUTION and isinstance(
result, ExperimentalIncrementalExecutionResults
):
if isinstance(result, ExperimentalIncrementalExecutionResults):

async def stream():
yield "---"
Expand Down Expand Up @@ -524,9 +522,16 @@ async def parse_http_body(
protocol=protocol,
)

def process_incremental_result(
async def process_incremental_result(

Check warning on line 525 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L525

Added line #L525 was not covered by tests
self, request: Request, result: IncrementalResult
) -> GraphQLHTTPResponse:
result = await self.schema._handle_execution_result(

Check warning on line 528 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L528

Added line #L528 was not covered by tests
context=self.schema.execution_context,
result=result,
extensions_runner=self.schema.extensions_runner,
process_errors=self.schema.process_errors,
)

if isinstance(result, IncrementalDeferResult):
return {

Check warning on line 536 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L536

Added line #L536 was not covered by tests
"data": result.data,
Expand Down Expand Up @@ -568,6 +573,12 @@ async def process_result(
result: Union[ExecutionResult, InitialIncrementalExecutionResult],
) -> GraphQLHTTPResponse:
if not isinstance(result, InitialIncrementalExecutionResult):
result = await self.schema._handle_execution_result(

Check warning on line 576 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L576

Added line #L576 was not covered by tests
context=self.schema.execution_context,
result=result,
extensions_runner=self.schema.extensions_runner,
process_errors=self.schema.process_errors,
)
return process_result(result)

Check warning on line 582 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L582

Added line #L582 was not covered by tests

return {

Check warning on line 584 in strawberry/http/async_base_view.py

View check run for this annotation

Codecov / codecov/patch

strawberry/http/async_base_view.py#L584

Added line #L584 was not covered by tests
Expand Down
58 changes: 25 additions & 33 deletions strawberry/schema/execute.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,6 +25,26 @@

from .exceptions import InvalidOperationTypeError

try:
from graphql.execution.execute import (
ExperimentalIncrementalExecutionResults,
InitialIncrementalExecutionResult,
)
from graphql.execution.incremental_publisher import (
IncrementalDeferResult,
IncrementalResult,
IncrementalStreamResult,
SubsequentIncrementalExecutionResult,
)

except ImportError:
from types import NoneType

Check warning on line 41 in strawberry/schema/execute.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/execute.py#L40-L41

Added lines #L40 - L41 were not covered by tests

InitialIncrementalExecutionResult = NoneType
IncrementalResult = NoneType
IncrementalStreamResult = NoneType
SubsequentIncrementalExecutionResult = NoneType

Check warning on line 46 in strawberry/schema/execute.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/execute.py#L43-L46

Added lines #L43 - L46 were not covered by tests

if TYPE_CHECKING:
from typing_extensions import NotRequired, TypeAlias, Unpack

Expand Down Expand Up @@ -115,26 +135,6 @@ async def _parse_and_validate_async(
return None


async def _handle_execution_result(
context: ExecutionContext,
result: Union[GraphQLExecutionResult, ExecutionResult],
extensions_runner: SchemaExtensionsRunner,
process_errors: ProcessErrors | None,
) -> ExecutionResult:
# TODO: deal with this later
# # Set errors on the context so that it's easier
# # to access in extensions
# if result.errors:
# context.errors = result.errors
# if process_errors:
# process_errors(result.errors, context)
# if isinstance(result, GraphQLExecutionResult):
# result = ExecutionResult(data=result.data, errors=result.errors)
# result.extensions = await extensions_runner.get_extensions_results(context)
# context.result = result # type: ignore # mypy failed to deduce correct type.
return result


def _coerce_error(error: Union[GraphQLError, Exception]) -> GraphQLError:
if isinstance(error, GraphQLError):
return error
Expand All @@ -157,9 +157,8 @@ async def execute(
if errors := await _parse_and_validate_async(
execution_context, extensions_runner
):
return await _handle_execution_result(
execution_context, errors, extensions_runner, process_errors
)
# TODO: ...
return errors

Check warning on line 161 in strawberry/schema/execute.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/execute.py#L161

Added line #L161 was not covered by tests

assert execution_context.graphql_document
async with extensions_runner.executing():
Expand Down Expand Up @@ -195,16 +194,9 @@ async def execute(
except (MissingQueryError, InvalidOperationTypeError):
raise
except Exception as exc: # noqa: BLE001
return await _handle_execution_result(
execution_context,
PreExecutionError(data=None, errors=[_coerce_error(exc)]),
extensions_runner,
process_errors,
)
# return results after all the operation completed.
return await _handle_execution_result(
execution_context, result, extensions_runner, None
)
return PreExecutionError(data=None, errors=[_coerce_error(exc)])

Check warning on line 197 in strawberry/schema/execute.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/execute.py#L197

Added line #L197 was not covered by tests

return result

Check warning on line 199 in strawberry/schema/execute.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/execute.py#L199

Added line #L199 was not covered by tests


def execute_sync(
Expand Down
44 changes: 39 additions & 5 deletions strawberry/schema/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,13 +5,16 @@
from typing import (
TYPE_CHECKING,
Any,
Callable,
Optional,
Union,
cast,
)

from graphql import ExecutionResult as GraphQLExecutionResult
from graphql import (
GraphQLBoolean,
GraphQLError,
GraphQLField,
GraphQLNamedType,
GraphQLNonNull,
Expand All @@ -37,7 +40,7 @@
from strawberry.printer import print_schema
from strawberry.schema.schema_converter import GraphQLCoreConverter
from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY
from strawberry.types import ExecutionContext
from strawberry.types import ExecutionContext, ExecutionResult
from strawberry.types.base import (
StrawberryObjectDefinition,
WithStrawberryObjectDefinition,
Expand All @@ -53,17 +56,21 @@

if TYPE_CHECKING:
from collections.abc import Iterable
from typing_extensions import TypeAlias

from graphql import ExecutionContext as GraphQLExecutionContext

from strawberry.directive import StrawberryDirective
from strawberry.types import ExecutionResult
from strawberry.types.base import StrawberryType
from strawberry.types.enum import EnumDefinition
from strawberry.types.field import StrawberryField
from strawberry.types.scalar import ScalarDefinition, ScalarWrapper
from strawberry.types.union import StrawberryUnion

ProcessErrors: TypeAlias = (
"Callable[[list[GraphQLError], Optional[ExecutionContext]], None]"
)

DEFAULT_ALLOWED_OPERATION_TYPES = {
OperationType.QUERY,
OperationType.MUTATION,
Expand Down Expand Up @@ -293,6 +300,30 @@ def _create_execution_context(
provided_operation_name=operation_name,
)

# TODO: is this the right place to do this?
async def _handle_execution_result(
self,
context: ExecutionContext,
result: Union[GraphQLExecutionResult, ExecutionResult],
extensions_runner: SchemaExtensionsRunner,
process_errors: ProcessErrors | None,
) -> ExecutionResult:
# Set errors on the context so that it's easier
# to access in extensions
if result.errors:
context.errors = result.errors

Check warning on line 314 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L314

Added line #L314 was not covered by tests

if process_errors:
process_errors(result.errors, context)

Check warning on line 317 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L317

Added line #L317 was not covered by tests

if isinstance(result, GraphQLExecutionResult):
result = ExecutionResult(data=result.data, errors=result.errors)

Check warning on line 320 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L320

Added line #L320 was not covered by tests

result.extensions = await extensions_runner.get_extensions_results(context)

Check warning on line 322 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L322

Added line #L322 was not covered by tests

context.result = result # type: ignore # mypy failed to deduce correct type.
return result

Check warning on line 325 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L324-L325

Added lines #L324 - L325 were not covered by tests

@lru_cache
def get_type_by_name(
self, name: str
Expand Down Expand Up @@ -369,12 +400,15 @@ async def execute(
# TODO (#3571): remove this when we implement execution context as parameter.
for extension in extensions:
extension.execution_context = execution_context
# TODO: fix (race conditions, ugly code)
self.execution_context = execution_context
self.extensions_runner = self.create_extensions_runner(

Check warning on line 405 in strawberry/schema/schema.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/schema.py#L404-L405

Added lines #L404 - L405 were not covered by tests
execution_context, extensions
)
return await execute(
self._schema,
execution_context=execution_context,
extensions_runner=self.create_extensions_runner(
execution_context, extensions
),
extensions_runner=self.extensions_runner,
process_errors=self._process_errors,
middleware_manager=self._get_middleware_manager(extensions),
execution_context_class=self.execution_context_class,
Expand Down
10 changes: 9 additions & 1 deletion strawberry/schema/subscribe.py
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,6 @@
from .execute import (
ProcessErrors,
_coerce_error,
_handle_execution_result,
_parse_and_validate_async,
)

Expand All @@ -39,6 +38,15 @@
]


def _handle_execution_result(
context: ExecutionContext,
result: Union[GraphQLExecutionResult, ExecutionResult],
extensions_runner: SchemaExtensionsRunner,
process_errors: ProcessErrors | None,
) -> ExecutionResult:
pass

Check warning on line 47 in strawberry/schema/subscribe.py

View check run for this annotation

Codecov / codecov/patch

strawberry/schema/subscribe.py#L47

Added line #L47 was not covered by tests


async def _subscribe(
schema: GraphQLSchema,
execution_context: ExecutionContext,
Expand Down
9 changes: 8 additions & 1 deletion tests/http/incremental/test_defer.py
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,20 @@ async def test_basic_defer(method: Literal["get", "post"], http_client: HttpClie
"data": {"hello": "Hello world"},
"incremental": [],
"hasNext": True,
# TODO: why is this None?
"extensions": None,
}

subsequent = await stream.__anext__()

Check warning on line 33 in tests/http/incremental/test_defer.py

View check run for this annotation

Codecov / codecov/patch

tests/http/incremental/test_defer.py#L33

Added line #L33 was not covered by tests

assert subsequent == {

Check warning on line 35 in tests/http/incremental/test_defer.py

View check run for this annotation

Codecov / codecov/patch

tests/http/incremental/test_defer.py#L35

Added line #L35 was not covered by tests
"incremental": [{"data": {"asyncHello": "Hello world"}}],
"incremental": [
{
"data": {"asyncHello": "Hello world"},
"extensions": {"example": "example"},
}
],
"hasNext": False,
# TODO: how do we fill these?
"extensions": None,
}

0 comments on commit eb43d5e

Please sign in to comment.