From b759723a7697bce250edb22d56f11847b6410518 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Tue, 2 Jul 2024 08:23:17 +0300 Subject: [PATCH 01/10] wip: add failing tests --- tests/execution/test_middleware.py | 98 ++++++++++++++++-------------- 1 file changed, 52 insertions(+), 46 deletions(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 4927b52f..b330bf26 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -5,15 +5,21 @@ from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString - -def describe_middleware(): - def describe_with_manager(): - def default(): +def _create_schema(tp: GraphQLObjectType, is_subscription: bool) -> GraphQLSchema: + if is_subscription: + noop_type = GraphQLObjectType("Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")}) + return GraphQLSchema(query=noop_type, subscription=tp) + return GraphQLSchema(tp) +@pytest.mark.parametrize("is_subscription", [False, True], ids=["query", "subscription"]) +def test_describe_middleware(is_subscription: bool): + + def test_test_describe_with_manager(): + def test_default(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def field(self, _info): + def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -22,20 +28,20 @@ def field(self, _info): middlewares = MiddlewareManager() result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data["field"] == "resolved" # type: ignore - def single_function(): + def test_single_function(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - def first(self, _info): + def test_first(self, _info): return "one" - def second(self, _info): + def test_second(self, _info): return "two" test_type = GraphQLObjectType( @@ -51,12 +57,12 @@ def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore - def two_functions_and_field_resolvers(): + def test_two_functions_and_field_resolvers(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic @@ -84,21 +90,21 @@ def capitalize_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, capitalize_middleware) result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"first": "Eno", "second": "Owt"} # type: ignore @pytest.mark.asyncio() - async def single_async_function(): + async def test_single_async_function(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - async def first(self, _info): + async def test_first(self, _info): return "one" - async def second(self, _info): + async def test_second(self, _info): return "two" test_type = GraphQLObjectType( @@ -114,21 +120,21 @@ async def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) awaitable_result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result assert result.data == {"first": "eno", "second": "owt"} - def single_object(): + def test_single_object(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - def first(self, _info): + def test_first(self, _info): return "one" - def second(self, _info): + def test_second(self, _info): return "two" test_type = GraphQLObjectType( @@ -141,17 +147,17 @@ def second(self, _info): class ReverseMiddleware: # noinspection PyMethodMayBeStatic - def resolve(self, next_, *args, **kwargs): + def test_resolve(self, next_, *args, **kwargs): return next_(*args, **kwargs)[::-1] middlewares = MiddlewareManager(ReverseMiddleware()) result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore - def skip_middleware_without_resolve_method(): + def test_skip_middleware_without_resolve_method(): class BadMiddleware: pass # no resolve method here @@ -167,12 +173,12 @@ class BadMiddleware: middleware=MiddlewareManager(BadMiddleware()), ) == ({"foo": "bar"}, None) - def with_function_and_object(): + def test_with_function_and_object(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def field(self, _info): + def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -184,28 +190,28 @@ def reverse_middleware(next_, *args, **kwargs): class CaptitalizeMiddleware: # noinspection PyMethodMayBeStatic - def resolve(self, next_, *args, **kwargs): + def test_resolve(self, next_, *args, **kwargs): return next_(*args, **kwargs).capitalize() middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"field": "Devloser"} # type: ignore middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"field": "devloseR"} # type: ignore @pytest.mark.asyncio() - async def with_async_function_and_object(): + async def test_with_async_function_and_object(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - async def field(self, _info): + async def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -217,12 +223,12 @@ async def reverse_middleware(next_, *args, **kwargs): class CaptitalizeMiddleware: # noinspection PyMethodMayBeStatic - async def resolve(self, next_, *args, **kwargs): + async def test_resolve(self, next_, *args, **kwargs): return (await next_(*args, **kwargs)).capitalize() middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) awaitable_result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result @@ -230,46 +236,46 @@ async def resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) awaitable_result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result assert result.data == {"field": "devloseR"} - def describe_without_manager(): - def no_middleware(): + def test_describe_without_manager(): + def test_no_middleware(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def field(self, _info): + def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(GraphQLSchema(test_type), doc, Data(), middleware=None) + result = execute(_create_schema(test_type, is_subscription), doc, Data(), middleware=None) assert result.data["field"] == "resolved" # type: ignore - def empty_middleware_list(): + def test_empty_middleware_list(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def field(self, _info): + def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(GraphQLSchema(test_type), doc, Data(), middleware=[]) + result = execute(_create_schema(test_type, is_subscription), doc, Data(), middleware=[]) assert result.data["field"] == "resolved" # type: ignore - def bad_middleware_object(): + def test_bad_middleware_object(): doc = parse("{ field }") test_type = GraphQLObjectType( @@ -279,7 +285,7 @@ def bad_middleware_object(): with pytest.raises(TypeError) as exc_info: # noinspection PyTypeChecker execute( - GraphQLSchema(test_type), + _create_schema(test_type, is_subscription), doc, None, middleware=cast(Middleware, {"bad": "value"}), @@ -291,12 +297,12 @@ def bad_middleware_object(): " Got {'bad': 'value'} instead." ) - def list_of_functions(): + def test_list_of_functions(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def field(self, _info): + def test_field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -306,11 +312,11 @@ def field(self, _info): log = [] class LogMiddleware: - def __init__(self, name): + def test___init__(self, name): self.name = name # noinspection PyMethodMayBeStatic - def resolve(self, next_, *args, **kwargs): + def test_resolve(self, next_, *args, **kwargs): log.append(f"enter {self.name}") value = next_(*args, **kwargs) log.append(f"exit {self.name}") @@ -319,7 +325,7 @@ def resolve(self, next_, *args, **kwargs): middlewares = [LogMiddleware("A"), LogMiddleware("B"), LogMiddleware("C")] result = execute( - GraphQLSchema(test_type), doc, Data(), middleware=middlewares + _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares ) assert result.data == {"field": "resolved"} # type: ignore From 613fe7b6d0645f326edce18cd4863e2f3060cf41 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Tue, 2 Jul 2024 14:50:01 +0300 Subject: [PATCH 02/10] initial test pass --- src/graphql/execution/execute.py | 2 + tests/execution/test_middleware.py | 133 +++++++++++++++++++---------- 2 files changed, 88 insertions(+), 47 deletions(-) diff --git a/src/graphql/execution/execute.py b/src/graphql/execution/execute.py index 7d3d85ed..15d22ce2 100644 --- a/src/graphql/execution/execute.py +++ b/src/graphql/execution/execute.py @@ -2043,6 +2043,7 @@ def subscribe( type_resolver: GraphQLTypeResolver | None = None, subscribe_field_resolver: GraphQLFieldResolver | None = None, execution_context_class: type[ExecutionContext] | None = None, + middleware: MiddlewareManager | None = None, ) -> AwaitableOrValue[AsyncIterator[ExecutionResult] | ExecutionResult]: """Create a GraphQL subscription. @@ -2082,6 +2083,7 @@ def subscribe( field_resolver, type_resolver, subscribe_field_resolver, + middleware=middleware, ) # Return early errors if execution context failed. diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index b330bf26..30202560 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -1,25 +1,32 @@ +import inspect from typing import Awaitable, cast import pytest +from graphql import subscribe from graphql.execution import Middleware, MiddlewareManager, execute from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -def _create_schema(tp: GraphQLObjectType, is_subscription: bool) -> GraphQLSchema: + +def _create_schema( + tp: GraphQLObjectType, is_subscription: bool = False +) -> GraphQLSchema: if is_subscription: - noop_type = GraphQLObjectType("Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")}) + noop_type = GraphQLObjectType( + "Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")} + ) return GraphQLSchema(query=noop_type, subscription=tp) return GraphQLSchema(tp) -@pytest.mark.parametrize("is_subscription", [False, True], ids=["query", "subscription"]) -def test_describe_middleware(is_subscription: bool): - def test_test_describe_with_manager(): - def test_default(): + +def describe_middleware(): + def describe_with_manager(): + def default(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def test_field(self, _info): + def field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -28,20 +35,20 @@ def test_field(self, _info): middlewares = MiddlewareManager() result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data["field"] == "resolved" # type: ignore - def test_single_function(): + def single_function(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - def test_first(self, _info): + def first(self, _info): return "one" - def test_second(self, _info): + def second(self, _info): return "two" test_type = GraphQLObjectType( @@ -57,12 +64,12 @@ def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore - def test_two_functions_and_field_resolvers(): + def two_functions_and_field_resolvers(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic @@ -90,21 +97,21 @@ def capitalize_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, capitalize_middleware) result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "Eno", "second": "Owt"} # type: ignore @pytest.mark.asyncio() - async def test_single_async_function(): + async def single_async_function(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - async def test_first(self, _info): + async def first(self, _info): return "one" - async def test_second(self, _info): + async def second(self, _info): return "two" test_type = GraphQLObjectType( @@ -120,21 +127,21 @@ async def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) awaitable_result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result assert result.data == {"first": "eno", "second": "owt"} - def test_single_object(): + def single_object(): doc = parse("{ first second }") # noinspection PyMethodMayBeStatic class Data: - def test_first(self, _info): + def first(self, _info): return "one" - def test_second(self, _info): + def second(self, _info): return "two" test_type = GraphQLObjectType( @@ -147,17 +154,17 @@ def test_second(self, _info): class ReverseMiddleware: # noinspection PyMethodMayBeStatic - def test_resolve(self, next_, *args, **kwargs): + def resolve(self, next_, *args, **kwargs): return next_(*args, **kwargs)[::-1] middlewares = MiddlewareManager(ReverseMiddleware()) result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore - def test_skip_middleware_without_resolve_method(): + def skip_middleware_without_resolve_method(): class BadMiddleware: pass # no resolve method here @@ -173,12 +180,12 @@ class BadMiddleware: middleware=MiddlewareManager(BadMiddleware()), ) == ({"foo": "bar"}, None) - def test_with_function_and_object(): + def with_function_and_object(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def test_field(self, _info): + def field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -190,28 +197,28 @@ def reverse_middleware(next_, *args, **kwargs): class CaptitalizeMiddleware: # noinspection PyMethodMayBeStatic - def test_resolve(self, next_, *args, **kwargs): + def resolve(self, next_, *args, **kwargs): return next_(*args, **kwargs).capitalize() middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "Devloser"} # type: ignore middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "devloseR"} # type: ignore @pytest.mark.asyncio() - async def test_with_async_function_and_object(): + async def with_async_function_and_object(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - async def test_field(self, _info): + async def field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -228,7 +235,7 @@ async def test_resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) awaitable_result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result @@ -236,46 +243,78 @@ async def test_resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) awaitable_result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result assert result.data == {"field": "devloseR"} - def test_describe_without_manager(): - def test_no_middleware(): + @pytest.mark.asyncio() + async def subscription_simple(): + async def bar_resolve(_obj, _info): + yield "bar" + + test_type = GraphQLObjectType( + "Subscription", + { + "bar": GraphQLField( + GraphQLString, + resolve=lambda message, _: message, + subscribe=bar_resolve, + ), + }, + ) + doc = parse("subscription { bar }") + + async def reverse_middleware(next_, value, info, **kwargs): + awaitable_maybe = next_(value, info, **kwargs) + if inspect.isawaitable(awaitable_maybe): + return (await awaitable_maybe)[::-1] + return awaitable_maybe[::-1] + + agen = subscribe( + _create_schema(test_type, is_subscription=True), + doc, + middleware=MiddlewareManager(reverse_middleware), + ) + assert inspect.isasyncgen(agen) + data = (await agen.__anext__()).data + assert data == {"bar": "rab"} + + def describe_without_manager(): + def no_middleware(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def test_field(self, _info): + def field(self, _info): return "resolved" test_type = GraphQLObjectType( "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(_create_schema(test_type, is_subscription), doc, Data(), middleware=None) + result = execute(_create_schema(test_type), doc, Data(), middleware=None) assert result.data["field"] == "resolved" # type: ignore - def test_empty_middleware_list(): + def empty_middleware_list(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def test_field(self, _info): + def field(self, _info): return "resolved" test_type = GraphQLObjectType( "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(_create_schema(test_type, is_subscription), doc, Data(), middleware=[]) + result = execute(_create_schema(test_type), doc, Data(), middleware=[]) assert result.data["field"] == "resolved" # type: ignore - def test_bad_middleware_object(): + def bad_middleware_object(): doc = parse("{ field }") test_type = GraphQLObjectType( @@ -285,7 +324,7 @@ def test_bad_middleware_object(): with pytest.raises(TypeError) as exc_info: # noinspection PyTypeChecker execute( - _create_schema(test_type, is_subscription), + _create_schema(test_type), doc, None, middleware=cast(Middleware, {"bad": "value"}), @@ -297,12 +336,12 @@ def test_bad_middleware_object(): " Got {'bad': 'value'} instead." ) - def test_list_of_functions(): + def list_of_functions(): doc = parse("{ field }") # noinspection PyMethodMayBeStatic class Data: - def test_field(self, _info): + def field(self, _info): return "resolved" test_type = GraphQLObjectType( @@ -312,11 +351,11 @@ def test_field(self, _info): log = [] class LogMiddleware: - def test___init__(self, name): + def __init__(self, name): self.name = name # noinspection PyMethodMayBeStatic - def test_resolve(self, next_, *args, **kwargs): + def resolve(self, next_, *args, **kwargs): log.append(f"enter {self.name}") value = next_(*args, **kwargs) log.append(f"exit {self.name}") @@ -325,7 +364,7 @@ def test_resolve(self, next_, *args, **kwargs): middlewares = [LogMiddleware("A"), LogMiddleware("B"), LogMiddleware("C")] result = execute( - _create_schema(test_type, is_subscription), doc, Data(), middleware=middlewares + _create_schema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "resolved"} # type: ignore From 04e9767f3ff7dce622730af8369d92696fde5c40 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:09:17 +0300 Subject: [PATCH 03/10] remove unneeded changes --- tests/execution/test_middleware.py | 42 ++++++++++++++---------------- 1 file changed, 19 insertions(+), 23 deletions(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 30202560..41e2c0ce 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -8,15 +8,11 @@ from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -def _create_schema( - tp: GraphQLObjectType, is_subscription: bool = False -) -> GraphQLSchema: - if is_subscription: - noop_type = GraphQLObjectType( - "Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")} - ) - return GraphQLSchema(query=noop_type, subscription=tp) - return GraphQLSchema(tp) +def _create_subscription_schema(tp: GraphQLObjectType) -> GraphQLSchema: + noop_type = GraphQLObjectType( + "Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")} + ) + return GraphQLSchema(query=noop_type, subscription=tp) def describe_middleware(): @@ -35,7 +31,7 @@ def field(self, _info): middlewares = MiddlewareManager() result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data["field"] == "resolved" # type: ignore @@ -64,7 +60,7 @@ def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore @@ -97,7 +93,7 @@ def capitalize_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, capitalize_middleware) result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "Eno", "second": "Owt"} # type: ignore @@ -127,7 +123,7 @@ async def reverse_middleware(next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware) awaitable_result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result @@ -159,7 +155,7 @@ def resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(ReverseMiddleware()) result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"first": "eno", "second": "owt"} # type: ignore @@ -202,13 +198,13 @@ def resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "Devloser"} # type: ignore middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "devloseR"} # type: ignore @@ -235,7 +231,7 @@ async def test_resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) awaitable_result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result @@ -243,7 +239,7 @@ async def test_resolve(self, next_, *args, **kwargs): middlewares = MiddlewareManager(CaptitalizeMiddleware(), reverse_middleware) awaitable_result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert isinstance(awaitable_result, Awaitable) result = await awaitable_result @@ -273,7 +269,7 @@ async def reverse_middleware(next_, value, info, **kwargs): return awaitable_maybe[::-1] agen = subscribe( - _create_schema(test_type, is_subscription=True), + _create_subscription_schema(test_type), doc, middleware=MiddlewareManager(reverse_middleware), ) @@ -294,7 +290,7 @@ def field(self, _info): "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(_create_schema(test_type), doc, Data(), middleware=None) + result = execute(GraphQLSchema(test_type), doc, Data(), middleware=None) assert result.data["field"] == "resolved" # type: ignore @@ -310,7 +306,7 @@ def field(self, _info): "TestType", {"field": GraphQLField(GraphQLString)} ) - result = execute(_create_schema(test_type), doc, Data(), middleware=[]) + result = execute(GraphQLSchema(test_type), doc, Data(), middleware=[]) assert result.data["field"] == "resolved" # type: ignore @@ -324,7 +320,7 @@ def bad_middleware_object(): with pytest.raises(TypeError) as exc_info: # noinspection PyTypeChecker execute( - _create_schema(test_type), + GraphQLSchema(test_type), doc, None, middleware=cast(Middleware, {"bad": "value"}), @@ -364,7 +360,7 @@ def resolve(self, next_, *args, **kwargs): middlewares = [LogMiddleware("A"), LogMiddleware("B"), LogMiddleware("C")] result = execute( - _create_schema(test_type), doc, Data(), middleware=middlewares + GraphQLSchema(test_type), doc, Data(), middleware=middlewares ) assert result.data == {"field": "resolved"} # type: ignore From 00731aa94a8ec48a4474bf8a22e740376f19260a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Tue, 2 Jul 2024 15:14:17 +0300 Subject: [PATCH 04/10] fix regressions. --- tests/execution/test_middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 41e2c0ce..f8b284fc 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -226,7 +226,7 @@ async def reverse_middleware(next_, *args, **kwargs): class CaptitalizeMiddleware: # noinspection PyMethodMayBeStatic - async def test_resolve(self, next_, *args, **kwargs): + async def resolve(self, next_, *args, **kwargs): return (await next_(*args, **kwargs)).capitalize() middlewares = MiddlewareManager(reverse_middleware, CaptitalizeMiddleware()) From 5b8febac5b10ae337fe65a3e6372df46b091c783 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 07:44:00 +0300 Subject: [PATCH 05/10] fix cov --- tests/execution/test_middleware.py | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index f8b284fc..f9b4d10b 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -247,9 +247,10 @@ async def resolve(self, next_, *args, **kwargs): @pytest.mark.asyncio() async def subscription_simple(): + async def bar_resolve(_obj, _info): yield "bar" - + yield "oof" test_type = GraphQLObjectType( "Subscription", { @@ -264,8 +265,6 @@ async def bar_resolve(_obj, _info): async def reverse_middleware(next_, value, info, **kwargs): awaitable_maybe = next_(value, info, **kwargs) - if inspect.isawaitable(awaitable_maybe): - return (await awaitable_maybe)[::-1] return awaitable_maybe[::-1] agen = subscribe( @@ -276,6 +275,8 @@ async def reverse_middleware(next_, value, info, **kwargs): assert inspect.isasyncgen(agen) data = (await agen.__anext__()).data assert data == {"bar": "rab"} + data = (await agen.__anext__()).data + assert data == {"bar": "foo"} def describe_without_manager(): def no_middleware(): From 81b0c570c488a399cfa3056ee3c10231c72998d1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:45:48 +0300 Subject: [PATCH 06/10] Update tests/execution/test_middleware.py Co-authored-by: Christoph Zwerschke --- tests/execution/test_middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index f9b4d10b..fc31ac7c 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -256,7 +256,7 @@ async def bar_resolve(_obj, _info): { "bar": GraphQLField( GraphQLString, - resolve=lambda message, _: message, + resolve=lambda message, _info: message, subscribe=bar_resolve, ), }, From 7e4b9fc7bbc29c26b48a6622c82ac54b87ed9f4b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:46:22 +0300 Subject: [PATCH 07/10] Update tests/execution/test_middleware.py Co-authored-by: Christoph Zwerschke --- tests/execution/test_middleware.py | 1 + 1 file changed, 1 insertion(+) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index fc31ac7c..8df139d0 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -251,6 +251,7 @@ async def subscription_simple(): async def bar_resolve(_obj, _info): yield "bar" yield "oof" + test_type = GraphQLObjectType( "Subscription", { From 70866d7a32c3feb8c7a0606d07cca6d88f7751bd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:46:42 +0300 Subject: [PATCH 08/10] Update tests/execution/test_middleware.py Co-authored-by: Christoph Zwerschke --- tests/execution/test_middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 8df139d0..2c31e1ec 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -2,7 +2,7 @@ from typing import Awaitable, cast import pytest -from graphql import subscribe +from graphql.execution import Middleware, MiddlewareManager, execute, subscribe from graphql.execution import Middleware, MiddlewareManager, execute from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString From bd6c36f6a15fb5a05bb33a4aec69c6ef0cc5e0c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 21:51:59 +0300 Subject: [PATCH 09/10] review fiexes. --- tests/execution/test_middleware.py | 17 +++++++---------- 1 file changed, 7 insertions(+), 10 deletions(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 2c31e1ec..8e260a8b 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -3,18 +3,10 @@ import pytest from graphql.execution import Middleware, MiddlewareManager, execute, subscribe -from graphql.execution import Middleware, MiddlewareManager, execute from graphql.language.parser import parse from graphql.type import GraphQLField, GraphQLObjectType, GraphQLSchema, GraphQLString -def _create_subscription_schema(tp: GraphQLObjectType) -> GraphQLSchema: - noop_type = GraphQLObjectType( - "Noop", {"noop": GraphQLField(GraphQLString, resolve=lambda *_: "noop")} - ) - return GraphQLSchema(query=noop_type, subscription=tp) - - def describe_middleware(): def describe_with_manager(): def default(): @@ -247,7 +239,6 @@ async def resolve(self, next_, *args, **kwargs): @pytest.mark.asyncio() async def subscription_simple(): - async def bar_resolve(_obj, _info): yield "bar" yield "oof" @@ -268,8 +259,14 @@ async def reverse_middleware(next_, value, info, **kwargs): awaitable_maybe = next_(value, info, **kwargs) return awaitable_maybe[::-1] + noop_type = GraphQLObjectType( + "Noop", + {"noop": GraphQLField(GraphQLString, resolve=lambda *_args: "noop")}, + ) + schema = GraphQLSchema(query=noop_type, subscription=test_type) + agen = subscribe( - _create_subscription_schema(test_type), + schema, doc, middleware=MiddlewareManager(reverse_middleware), ) From 1a5b8599b831086c1dc55fec4d6ba38ff2579a46 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D7=A0=D7=99=D7=A8?= <88795475+nrbnlulu@users.noreply.github.com> Date: Sun, 7 Jul 2024 22:55:08 +0300 Subject: [PATCH 10/10] Update tests/execution/test_middleware.py Co-authored-by: Christoph Zwerschke --- tests/execution/test_middleware.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/execution/test_middleware.py b/tests/execution/test_middleware.py index 8e260a8b..d4abba95 100644 --- a/tests/execution/test_middleware.py +++ b/tests/execution/test_middleware.py @@ -261,7 +261,7 @@ async def reverse_middleware(next_, value, info, **kwargs): noop_type = GraphQLObjectType( "Noop", - {"noop": GraphQLField(GraphQLString, resolve=lambda *_args: "noop")}, + {"noop": GraphQLField(GraphQLString)}, ) schema = GraphQLSchema(query=noop_type, subscription=test_type)