From 4cf4fc547d0b630aaab751e188621a75e2691806 Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 13:31:59 -0400 Subject: [PATCH 1/7] Delete an unused module --- nextlinegraphql/plugins/ctrl/test.py | 102 --------------------------- 1 file changed, 102 deletions(-) delete mode 100644 nextlinegraphql/plugins/ctrl/test.py diff --git a/nextlinegraphql/plugins/ctrl/test.py b/nextlinegraphql/plugins/ctrl/test.py deleted file mode 100644 index d579ace..0000000 --- a/nextlinegraphql/plugins/ctrl/test.py +++ /dev/null @@ -1,102 +0,0 @@ -import asyncio -from typing import Any, Optional - -from nextline.utils import agen_with_wait - -from nextlinegraphql.plugins.ctrl.graphql import ( - MUTATE_EXEC, - MUTATE_RESET, - MUTATE_SEND_PDB_COMMAND, - QUERY_STATE, - SUBSCRIBE_PROMPTING, - SUBSCRIBE_STATE, - SUBSCRIBE_TRACE_IDS, -) -from nextlinegraphql.plugins.graphql.test import TestClient, gql_request, gql_subscribe - - -async def run_statement(client, statement: Optional[str] = None): - variables = {"statement": statement} - data = await gql_request(client, MUTATE_RESET, variables=variables) - assert data["reset"] - - task_subscribe_state = asyncio.create_task(subscribe_state(client)) - - data = await gql_request(client, QUERY_STATE) - assert "initialized" == data["state"] - - await asyncio.sleep(0.01) - - task_control_execution = asyncio.create_task(control_execution(client)) - - await asyncio.sleep(0.01) - - data = await gql_request(client, MUTATE_EXEC) - assert data["exec"] - - states, *_ = await asyncio.gather( - task_subscribe_state, - task_control_execution, - ) - assert ["initialized", "running", "finished"] == states - - data = await gql_request(client, QUERY_STATE) - assert "finished" == data["state"] - - await asyncio.sleep(0.01) - - -async def subscribe_state(client: TestClient) -> list[str]: - ret = [] - async for data in gql_subscribe(client, SUBSCRIBE_STATE): - s = data["state"] - ret.append(s) - if s == "finished": - break - return ret - - -async def control_execution(client: TestClient): - agen = agen_with_wait(gql_subscribe(client, SUBSCRIBE_TRACE_IDS)) - data: Any - - prev_ids = set[int]() - async for data in agen: - if not (ids := set(data["traceIds"])): - break - new_ids, prev_ids = ids - prev_ids, ids - tasks = { - asyncio.create_task( - control_trace(client, id_), - ) - for id_ in new_ids - } - _, pending = await agen.asend(tasks) - - await asyncio.gather(*pending) - - -async def control_trace(client: TestClient, trace_no: int) -> None: - # print(f'control_trace({trace_id})') - - async for data in gql_subscribe( - client, - SUBSCRIBE_PROMPTING, - variables={"traceId": trace_no}, - ): - state = data["prompting"] - # print(state) - if state["prompting"]: - await asyncio.sleep(0.001) - command = "continue" - variables = { - "command": command, - "promptNo": state["prompting"], - "traceNo": trace_no, - } - data = await gql_request( - client, - MUTATE_SEND_PDB_COMMAND, - variables=variables, - ) - assert data["sendPdbCommand"] From 3ad75e0d3daf877a3f72fdf23bca7dbdb8bf2ee8 Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 13:48:26 -0400 Subject: [PATCH 2/7] Update coverage configuration --- pyproject.toml | 2 ++ 1 file changed, 2 insertions(+) diff --git a/pyproject.toml b/pyproject.toml index d2c1f4c..fd7b813 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -68,6 +68,7 @@ branch = true source = ["nextlinegraphql", "tests"] concurrency = ["multiprocessing"] omit = [ + "nextlinegraphql/plugins/ctrl/example_script/*", "venv/*", "*/site-packages/*", ] @@ -81,6 +82,7 @@ exclude_lines = [ "raise NotImplementedError", "if 0:", 'if __name__ == "__main__":', + "if TYPE_CHECKING:", ] ignore_errors = true From e7f1b590ac809d4cb71ca4a57967bba20dce71fe Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 13:59:09 -0400 Subject: [PATCH 3/7] Check syntax of GraphQL queries --- .../plugins/ctrl/graphql/__init__.py | 40 ++++++++++++------- 1 file changed, 26 insertions(+), 14 deletions(-) diff --git a/nextlinegraphql/plugins/ctrl/graphql/__init__.py b/nextlinegraphql/plugins/ctrl/graphql/__init__.py index 78e32de..056af3f 100644 --- a/nextlinegraphql/plugins/ctrl/graphql/__init__.py +++ b/nextlinegraphql/plugins/ctrl/graphql/__init__.py @@ -1,23 +1,35 @@ from pathlib import Path +from graphql import parse, print_ast + + +def read_gql(path: Path | str) -> str: + '''Load a GraphQL query from a file while checking its syntax.''' + + text = Path(path).read_text() + parsed = parse(text) + reformatted = print_ast(parsed) + return reformatted + + pwd = Path(__file__).resolve().parent sub = pwd / 'mutations' -MUTATE_EXEC = (sub / 'Exec.gql').read_text() -MUTATE_RESET = (sub / 'Reset.gql').read_text() -MUTATE_SEND_PDB_COMMAND = (sub / 'SendPdbCommand.gql').read_text() -MUTATE_RUN_AND_CONTINUE = (sub / 'RunAndContinue.gql').read_text() -MUTATE_LOAD_EXAMPLE_SCRIPT = (sub / 'LoadExampleScript.gql').read_text() +MUTATE_EXEC = read_gql(sub / 'Exec.gql') +MUTATE_RESET = read_gql(sub / 'Reset.gql') +MUTATE_SEND_PDB_COMMAND = read_gql(sub / 'SendPdbCommand.gql') +MUTATE_RUN_AND_CONTINUE = read_gql(sub / 'RunAndContinue.gql') +MUTATE_LOAD_EXAMPLE_SCRIPT = read_gql(sub / 'LoadExampleScript.gql') sub = pwd / 'queries' -QUERY_STATE = (sub / 'State.gql').read_text() -QUERY_EXCEPTION = (sub / 'Exception.gql').read_text() -QUERY_SOURCE = (sub / 'Source.gql').read_text() -QUERY_SOURCE_LINE = (sub / 'SourceLine.gql').read_text() +QUERY_STATE = read_gql(sub / 'State.gql') +QUERY_EXCEPTION = read_gql(sub / 'Exception.gql') +QUERY_SOURCE = read_gql(sub / 'Source.gql') +QUERY_SOURCE_LINE = read_gql(sub / 'SourceLine.gql') sub = pwd / 'subscriptions' -SUBSCRIBE_COUNTER = (sub / 'Counter.gql').read_text() -SUBSCRIBE_STATE = (sub / 'State.gql').read_text() -SUBSCRIBE_STDOUT = (sub / 'Stdout.gql').read_text() -SUBSCRIBE_TRACE_IDS = (sub / 'TraceIds.gql').read_text() -SUBSCRIBE_PROMPTING = (sub / 'Prompting.gql').read_text() +SUBSCRIBE_COUNTER = read_gql(sub / 'Counter.gql') +SUBSCRIBE_STATE = read_gql(sub / 'State.gql') +SUBSCRIBE_STDOUT = read_gql(sub / 'Stdout.gql') +SUBSCRIBE_TRACE_IDS = read_gql(sub / 'TraceIds.gql') +SUBSCRIBE_PROMPTING = read_gql(sub / 'Prompting.gql') From a6c7b6f4f2d698f536bcd705668d8083fa9d9395 Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 14:01:20 -0400 Subject: [PATCH 4/7] Check syntax of GraphQL queries --- .../plugins/graphql/graphql/__init__.py | 14 +++++++++++++- 1 file changed, 13 insertions(+), 1 deletion(-) diff --git a/nextlinegraphql/plugins/graphql/graphql/__init__.py b/nextlinegraphql/plugins/graphql/graphql/__init__.py index d162312..b862879 100644 --- a/nextlinegraphql/plugins/graphql/graphql/__init__.py +++ b/nextlinegraphql/plugins/graphql/graphql/__init__.py @@ -1,6 +1,18 @@ from pathlib import Path +from graphql import parse, print_ast + + +def read_gql(path: Path | str) -> str: + '''Load a GraphQL query from a file while checking its syntax.''' + + text = Path(path).read_text() + parsed = parse(text) + reformatted = print_ast(parsed) + return reformatted + + pwd = Path(__file__).resolve().parent sub = pwd / 'queries' -QUERY_SETTINGS = (sub / 'Settings.gql').read_text() +QUERY_SETTINGS = read_gql(sub / 'Settings.gql') From 115162a1ecaeedff8a54e9e3b34cf54cfbde8964 Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 14:31:11 -0400 Subject: [PATCH 5/7] Extract fixtures `schema` --- tests/plugins/ctrl/schema/conftest.py | 14 ++++++++++++++ .../schema/mutations/test_load_example_script.py | 6 ++---- tests/plugins/ctrl/schema/mutations/test_reset.py | 7 ++----- .../plugins/ctrl/schema/queries/test_exception.py | 7 ++----- tests/plugins/ctrl/schema/queries/test_source.py | 9 ++++----- tests/plugins/ctrl/schema/test_run.py | 7 ++----- tests/plugins/graphql/schema/conftest.py | 14 ++++++++++++++ .../graphql/schema/queries/test_settings.py | 6 ++---- 8 files changed, 42 insertions(+), 28 deletions(-) create mode 100644 tests/plugins/ctrl/schema/conftest.py create mode 100644 tests/plugins/graphql/schema/conftest.py diff --git a/tests/plugins/ctrl/schema/conftest.py b/tests/plugins/ctrl/schema/conftest.py new file mode 100644 index 0000000..575d525 --- /dev/null +++ b/tests/plugins/ctrl/schema/conftest.py @@ -0,0 +1,14 @@ +import pytest +from strawberry import Schema + +from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription + + +@pytest.fixture(scope='session') +def schema() -> Schema: + '''GraphQL schema + + The scope is `session` because Hypothesis doesn't allow function-scoped + fixtures. This is fine as the schema is stateless. + ''' + return Schema(query=Query, mutation=Mutation, subscription=Subscription) diff --git a/tests/plugins/ctrl/schema/mutations/test_load_example_script.py b/tests/plugins/ctrl/schema/mutations/test_load_example_script.py index ff02999..2fa9983 100644 --- a/tests/plugins/ctrl/schema/mutations/test_load_example_script.py +++ b/tests/plugins/ctrl/schema/mutations/test_load_example_script.py @@ -1,11 +1,10 @@ from pathlib import Path from nextline import Nextline -from strawberry import Schema from nextlinegraphql.plugins.ctrl import example_script as example_script_module from nextlinegraphql.plugins.ctrl.graphql import MUTATE_LOAD_EXAMPLE_SCRIPT -from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription +from tests.plugins.ctrl.schema.conftest import Schema EXAMPLE_SCRIPT_PATH = Path(example_script_module.__file__).parent / 'script.py' example_script = EXAMPLE_SCRIPT_PATH.read_text() @@ -16,11 +15,10 @@ '''.strip() -async def test_query() -> None: +async def test_query(schema: Schema) -> None: nextline = Nextline(INITIAL_SCRIPT) async with nextline: context = {'nextline': nextline} - schema = Schema(query=Query, mutation=Mutation, subscription=Subscription) result = await schema.execute(MUTATE_LOAD_EXAMPLE_SCRIPT, context_value=context) assert not result.errors assert result.data diff --git a/tests/plugins/ctrl/schema/mutations/test_reset.py b/tests/plugins/ctrl/schema/mutations/test_reset.py index fd6ad27..6a1c868 100644 --- a/tests/plugins/ctrl/schema/mutations/test_reset.py +++ b/tests/plugins/ctrl/schema/mutations/test_reset.py @@ -2,11 +2,10 @@ import pytest from nextline import Nextline -from strawberry import Schema from nextlinegraphql.plugins.ctrl import example_script as example_script_module from nextlinegraphql.plugins.ctrl.graphql import MUTATE_RESET, QUERY_SOURCE -from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription +from tests.plugins.ctrl.schema.conftest import Schema EXAMPLE_SCRIPT_PATH = Path(example_script_module.__file__).parent / 'script.py' example_script = EXAMPLE_SCRIPT_PATH.read_text() @@ -23,9 +22,7 @@ @pytest.mark.parametrize('statement', params) -async def test_schema(statement: str | None) -> None: - schema = Schema(query=Query, mutation=Mutation, subscription=Subscription) - assert schema +async def test_schema(schema: Schema, statement: str | None) -> None: nextline = Nextline(example_script, trace_modules=True, trace_threads=True) async with nextline: context = {'nextline': nextline} diff --git a/tests/plugins/ctrl/schema/queries/test_exception.py b/tests/plugins/ctrl/schema/queries/test_exception.py index 67e5859..0791aac 100644 --- a/tests/plugins/ctrl/schema/queries/test_exception.py +++ b/tests/plugins/ctrl/schema/queries/test_exception.py @@ -1,17 +1,14 @@ from nextline import Nextline -from strawberry import Schema from nextlinegraphql.plugins.ctrl.graphql import QUERY_EXCEPTION -from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription +from tests.plugins.ctrl.schema.conftest import Schema SOURCE_RAISE = ''' raise Exception('foo', 'bar') '''.strip() -async def test_schema() -> None: - schema = Schema(query=Query, mutation=Mutation, subscription=Subscription) - assert schema +async def test_schema(schema: Schema) -> None: nextline = Nextline(SOURCE_RAISE, trace_modules=True, trace_threads=True) async with nextline: context = {'nextline': nextline} diff --git a/tests/plugins/ctrl/schema/queries/test_source.py b/tests/plugins/ctrl/schema/queries/test_source.py index 80227be..db9eff1 100644 --- a/tests/plugins/ctrl/schema/queries/test_source.py +++ b/tests/plugins/ctrl/schema/queries/test_source.py @@ -2,12 +2,11 @@ import pytest from nextline import Nextline -from strawberry import Schema from syrupy.assertion import SnapshotAssertion from nextlinegraphql.plugins.ctrl import example_script as example_script_module from nextlinegraphql.plugins.ctrl.graphql import QUERY_SOURCE -from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription +from tests.plugins.ctrl.schema.conftest import Schema EXAMPLE_SCRIPT_DIR = Path(example_script_module.__file__).resolve().parent EXAMPLE_SCRIPT_PATH = EXAMPLE_SCRIPT_DIR / 'script.py' @@ -23,9 +22,9 @@ @pytest.mark.parametrize('file_name', params) -async def test_schema(snapshot: SnapshotAssertion, file_name: str | None) -> None: - schema = Schema(query=Query, mutation=Mutation, subscription=Subscription) - assert schema +async def test_schema( + schema: Schema, snapshot: SnapshotAssertion, file_name: str | None +) -> None: nextline = Nextline(example_script, trace_modules=True, trace_threads=True) async with nextline: context = {'nextline': nextline} diff --git a/tests/plugins/ctrl/schema/test_run.py b/tests/plugins/ctrl/schema/test_run.py index 94b9ea4..e3b9e70 100644 --- a/tests/plugins/ctrl/schema/test_run.py +++ b/tests/plugins/ctrl/schema/test_run.py @@ -5,7 +5,6 @@ from graphql import ExecutionResult as GraphQLExecutionResult from nextline import Nextline from nextline.utils import agen_with_wait -from strawberry import Schema from nextlinegraphql.plugins.ctrl import example_script as example_script_module from nextlinegraphql.plugins.ctrl.graphql import ( @@ -17,15 +16,13 @@ SUBSCRIBE_STATE, SUBSCRIBE_TRACE_IDS, ) -from nextlinegraphql.plugins.ctrl.schema import Mutation, Query, Subscription +from tests.plugins.ctrl.schema.conftest import Schema EXAMPLE_SCRIPT_PATH = Path(example_script_module.__file__).parent / 'script.py' example_script = EXAMPLE_SCRIPT_PATH.read_text() -async def test_schema() -> None: - schema = Schema(query=Query, mutation=Mutation, subscription=Subscription) - assert schema +async def test_schema(schema: Schema) -> None: nextline = Nextline(example_script, trace_modules=True, trace_threads=True) async with nextline: context = {'nextline': nextline} diff --git a/tests/plugins/graphql/schema/conftest.py b/tests/plugins/graphql/schema/conftest.py new file mode 100644 index 0000000..8635b1e --- /dev/null +++ b/tests/plugins/graphql/schema/conftest.py @@ -0,0 +1,14 @@ +import pytest +from strawberry import Schema + +from nextlinegraphql.plugins.graphql.schema import Query + + +@pytest.fixture(scope='session') +def schema() -> Schema: + '''GraphQL schema + + The scope is `session` because Hypothesis doesn't allow function-scoped + fixtures. This is fine as the schema is stateless. + ''' + return Schema(query=Query) diff --git a/tests/plugins/graphql/schema/queries/test_settings.py b/tests/plugins/graphql/schema/queries/test_settings.py index 85e9b7f..0e2de89 100644 --- a/tests/plugins/graphql/schema/queries/test_settings.py +++ b/tests/plugins/graphql/schema/queries/test_settings.py @@ -1,14 +1,12 @@ import json from dynaconf import Dynaconf -from strawberry import Schema from nextlinegraphql.plugins.graphql.graphql import QUERY_SETTINGS -from nextlinegraphql.plugins.graphql.schema import Query +from tests.plugins.graphql.schema.conftest import Schema -async def test_settings() -> None: - schema = Schema(query=Query) +async def test_settings(schema: Schema) -> None: settings = {'FOO': 'bar'} conf = Dynaconf(**settings) context = {'settings': conf} From f82a9ce8082063fab24574658fefc39aaf4674cd Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 15:00:00 -0400 Subject: [PATCH 6/7] Fix mypy errors with `--disallow-untyped-defs` --- nextlinegraphql/custom/strawberry.py | 9 +++++++-- nextlinegraphql/factory.py | 5 +++-- nextlinegraphql/hook/spec.py | 7 +++++-- nextlinegraphql/plugins/ctrl/__init__.py | 2 +- nextlinegraphql/plugins/dev/plugin.py | 2 +- nextlinegraphql/plugins/graphql/plugin.py | 17 ++++++++++++----- tests/app/test_cors.py | 4 ++-- tests/dynaconf/merge/test_merge.py | 10 ++++++---- .../examples/test_async_asgi_testclient.py | 4 ++-- tests/plugins/ctrl/test_plugin.py | 2 +- tests/plugins/graphql/test_graphiql.py | 2 +- tests/plugins/graphql/test_plugin.py | 2 +- tests/test_import_all.py | 2 +- tests/test_version.py | 2 +- 14 files changed, 44 insertions(+), 26 deletions(-) diff --git a/nextlinegraphql/custom/strawberry.py b/nextlinegraphql/custom/strawberry.py index ab9a931..f400c35 100644 --- a/nextlinegraphql/custom/strawberry.py +++ b/nextlinegraphql/custom/strawberry.py @@ -2,18 +2,23 @@ Strawberry: https://strawberry.rocks ''' +from typing import TYPE_CHECKING + from strawberry.asgi import GraphQL as GraphQL_ from strawberry.subscriptions import GRAPHQL_WS_PROTOCOL +if TYPE_CHECKING: + from strawberry.asgi import Receive, Scope, Send + class GraphQL(GraphQL_): """Add a fix to the strawberry GraphQL for async_asgi_testclient""" - async def __call__(self, scope, receive, send): + async def __call__(self, scope: 'Scope', receive: 'Receive', send: 'Send') -> None: if scope["type"] == "websocket": if not scope.get("subprotocols"): # strawberry closes the websocket connection if # subprotocols are empty, which is the case for # async_asgi_testclient. scope["subprotocols"] = [GRAPHQL_WS_PROTOCOL] - await super().__call__(scope, receive, send) + return await super().__call__(scope, receive, send) diff --git a/nextlinegraphql/factory.py b/nextlinegraphql/factory.py index d3f4977..77bae0d 100644 --- a/nextlinegraphql/factory.py +++ b/nextlinegraphql/factory.py @@ -1,5 +1,6 @@ import contextlib import logging.config +from collections.abc import AsyncIterator from logging import getLogger from typing import Any @@ -37,7 +38,7 @@ def create_app() -> Starlette: logger.info(f'Loaded plugins: {plugin_names}') @contextlib.asynccontextmanager - async def lifespan(app: Starlette): + async def lifespan(app: Starlette) -> AsyncIterator[None]: context = dict[Any, Any]() await hook.ahook.update_lifespan_context(app=app, hook=hook, context=context) async with hook.awith.lifespan(app=app, hook=hook, context=context): @@ -57,7 +58,7 @@ async def lifespan(app: Starlette): return app -def configure_logging(config: dict): +def configure_logging(config: dict) -> None: logging.config.dictConfig(config) # https://pypi.org/project/logging_tree/ diff --git a/nextlinegraphql/hook/spec.py b/nextlinegraphql/hook/spec.py index 0f1174c..066d91b 100644 --- a/nextlinegraphql/hook/spec.py +++ b/nextlinegraphql/hook/spec.py @@ -1,5 +1,5 @@ '''Hook specification for Nextline GraphQL plugin.''' -from collections.abc import MutableMapping, Sequence +from collections.abc import AsyncIterator, MutableMapping, Sequence from typing import Optional import apluggy as pluggy @@ -62,13 +62,16 @@ async def update_lifespan_context( @hookspec @asynccontextmanager -async def lifespan(app: Starlette, hook: pluggy.PluginManager, context: MutableMapping): +async def lifespan( + app: Starlette, hook: pluggy.PluginManager, context: MutableMapping +) -> AsyncIterator[None]: '''Called within the Starlette lifespan context. The context is passed from the update_lifespan_context hook. The Starlette lifespan yields within this hook ''' + yield @hookspec diff --git a/nextlinegraphql/plugins/ctrl/__init__.py b/nextlinegraphql/plugins/ctrl/__init__.py index 6346545..0151efd 100644 --- a/nextlinegraphql/plugins/ctrl/__init__.py +++ b/nextlinegraphql/plugins/ctrl/__init__.py @@ -17,7 +17,7 @@ class Plugin: @spec.hookimpl - def schema(self): + def schema(self) -> tuple[type, type | None, type | None]: return (Query, Mutation, Subscription) @spec.hookimpl diff --git a/nextlinegraphql/plugins/dev/plugin.py b/nextlinegraphql/plugins/dev/plugin.py index 441e852..efe1b11 100644 --- a/nextlinegraphql/plugins/dev/plugin.py +++ b/nextlinegraphql/plugins/dev/plugin.py @@ -12,5 +12,5 @@ def configure(self, settings: Dynaconf, hook: PluginManager) -> None: self._settings = settings @spec.hookimpl - def schema(self): + def schema(self) -> tuple[type, type | None, type | None]: return (Query, None, None) diff --git a/nextlinegraphql/plugins/graphql/plugin.py b/nextlinegraphql/plugins/graphql/plugin.py index 4701262..1a8d401 100644 --- a/nextlinegraphql/plugins/graphql/plugin.py +++ b/nextlinegraphql/plugins/graphql/plugin.py @@ -1,5 +1,5 @@ -from collections.abc import MutableMapping -from typing import Any, Optional +from collections.abc import AsyncIterator, MutableMapping +from typing import TYPE_CHECKING, Any, Optional import strawberry from apluggy import PluginManager, asynccontextmanager @@ -14,6 +14,9 @@ from .schema import Query +if TYPE_CHECKING: + from strawberry.asgi import Request, Response, WebSocket + class Plugin: @spec.hookimpl @@ -22,12 +25,12 @@ def configure(self, settings: Dynaconf, hook: PluginManager) -> None: self._app = _create_app(hook=hook) @spec.hookimpl - def schema(self): + def schema(self) -> tuple[type, type | None, type | None]: return (Query, None, None) @spec.hookimpl(tryfirst=True) # tryfirst so to be the outermost context @asynccontextmanager - async def lifespan(self, app: Starlette): + async def lifespan(self, app: Starlette) -> AsyncIterator[None]: app.mount('/', self._app) yield @@ -76,7 +79,11 @@ def set_hook(self, hook: PluginManager) -> '_EGraphQL': self._hook = hook return self - async def get_context(self, request, response=None) -> Optional[Any]: + async def get_context( + self, + request: 'Request | WebSocket', + response: Optional['Response'] = None, + ) -> Optional[Any]: context = {'request': request, 'response': response} self._hook.hook.update_strawberry_context(context=context) return context diff --git a/tests/app/test_cors.py b/tests/app/test_cors.py index e7d11b1..8339a80 100644 --- a/tests/app/test_cors.py +++ b/tests/app/test_cors.py @@ -1,7 +1,7 @@ from nextlinegraphql.plugins.graphql.test import TestClient -async def test_get(client: TestClient): +async def test_get(client: TestClient) -> None: '''test if CORSMiddleware is in effect The response header should include CORSMiddleware @@ -24,7 +24,7 @@ async def test_get(client: TestClient): assert resp.status_code == 200 -async def test_preflight(client: TestClient): +async def test_preflight(client: TestClient) -> None: '''test if CORSMiddleware is in effect with the preflighted request https://developer.mozilla.org/en-US/docs/Web/HTTP/CORS#preflighted_requests diff --git a/tests/dynaconf/merge/test_merge.py b/tests/dynaconf/merge/test_merge.py index e64da71..00a4d51 100644 --- a/tests/dynaconf/merge/test_merge.py +++ b/tests/dynaconf/merge/test_merge.py @@ -4,7 +4,7 @@ from pytest import FixtureRequest, MonkeyPatch, fixture -def test_merge(config: Dynaconf, envvar_url: bool, envvar_connect_args: bool): +def test_merge(config: Dynaconf, envvar_url: bool, envvar_connect_args: bool) -> None: '''Confirm how merging works https://www.dynaconf.com/merging/ @@ -30,7 +30,7 @@ def test_merge(config: Dynaconf, envvar_url: bool, envvar_connect_args: bool): @fixture -def config(): +def config() -> Dynaconf: here = Path(__file__).resolve().parent ret = Dynaconf( envvar_prefix='NEXTLINE', @@ -44,7 +44,7 @@ def config(): @fixture(params=[True, False]) -def envvar_url(request: FixtureRequest, monkeypatch: MonkeyPatch): +def envvar_url(request: FixtureRequest, monkeypatch: MonkeyPatch) -> bool: if ret := request.param: monkeypatch.setenv('NEXTLINE_DB__URL', 'sqlite:///env.sqlite3') # dunder merging @@ -53,7 +53,9 @@ def envvar_url(request: FixtureRequest, monkeypatch: MonkeyPatch): @fixture(params=[False, True, None]) -def envvar_connect_args(request: FixtureRequest, monkeypatch: MonkeyPatch): +def envvar_connect_args( + request: FixtureRequest, monkeypatch: MonkeyPatch +) -> bool | None: # False: intact # True: override # None: remove diff --git a/tests/plugins/ctrl/schema/examples/test_async_asgi_testclient.py b/tests/plugins/ctrl/schema/examples/test_async_asgi_testclient.py index ed5a074..2928398 100644 --- a/tests/plugins/ctrl/schema/examples/test_async_asgi_testclient.py +++ b/tests/plugins/ctrl/schema/examples/test_async_asgi_testclient.py @@ -2,7 +2,7 @@ from nextlinegraphql.plugins.graphql.test import TestClient -async def test_query(): +async def test_query() -> None: query = ''' { ctrl { hello } @@ -22,7 +22,7 @@ async def test_query(): assert expect == resp.json() -async def test_subscription(): +async def test_subscription() -> None: query = ''' subscription { ctrlCounter diff --git a/tests/plugins/ctrl/test_plugin.py b/tests/plugins/ctrl/test_plugin.py index 5148031..7762ac6 100644 --- a/tests/plugins/ctrl/test_plugin.py +++ b/tests/plugins/ctrl/test_plugin.py @@ -8,7 +8,7 @@ from nextlinegraphql.plugins.graphql.test import TestClient, gql_request, gql_subscribe -async def test_plugin(client: TestClient): +async def test_plugin(client: TestClient) -> None: data = await gql_request(client, QUERY_STATE) assert data['ctrl']['state'] == 'initialized' diff --git a/tests/plugins/graphql/test_graphiql.py b/tests/plugins/graphql/test_graphiql.py index b1453f3..9c62625 100644 --- a/tests/plugins/graphql/test_graphiql.py +++ b/tests/plugins/graphql/test_graphiql.py @@ -1,7 +1,7 @@ from nextlinegraphql.plugins.graphql.test import TestClient -async def test_one(client: TestClient): +async def test_one(client: TestClient) -> None: '''Assert GraphQL IDE for the HTTP get request''' headers = {'Accept': 'text/html'} resp = await client.get('/', headers=headers) diff --git a/tests/plugins/graphql/test_plugin.py b/tests/plugins/graphql/test_plugin.py index 7f2a478..5138b58 100644 --- a/tests/plugins/graphql/test_plugin.py +++ b/tests/plugins/graphql/test_plugin.py @@ -4,6 +4,6 @@ from nextlinegraphql.plugins.graphql.test import TestClient, gql_request -async def test_plugin(client: TestClient): +async def test_plugin(client: TestClient) -> None: data = await gql_request(client, QUERY_SETTINGS) assert json.loads(data['settings']) diff --git a/tests/test_import_all.py b/tests/test_import_all.py index 7c78a32..ac15eab 100644 --- a/tests/test_import_all.py +++ b/tests/test_import_all.py @@ -1,5 +1,5 @@ from nextlinegraphql import * # noqa: F403, F401 -def test_import_all(): +def test_import_all() -> None: assert 'create_app' in globals() diff --git a/tests/test_version.py b/tests/test_version.py index da895b8..b3027df 100644 --- a/tests/test_version.py +++ b/tests/test_version.py @@ -1,6 +1,6 @@ import nextlinegraphql -def test_version(): +def test_version() -> None: '''Confirm that the version string is attached to the module''' nextlinegraphql.__version__ From 2323ea6d4d654c2d76de470e541667b1b23cf3c3 Mon Sep 17 00:00:00 2001 From: Tai Sakuma Date: Mon, 24 Jun 2024 15:03:19 -0400 Subject: [PATCH 7/7] Update mypy configuration --- pyproject.toml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/pyproject.toml b/pyproject.toml index fd7b813..f635cd8 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -100,9 +100,9 @@ profile = "black" [tool.mypy] plugins = "strawberry.ext.mypy_plugin" exclude = '''(?x)( - db/alembic/versions/.*\.py$ - | example_script/.*\.py$ + example_script/.*\.py$ )''' +disallow_untyped_defs = true [[tool.mypy.overrides]] module = [