Skip to content

Commit

Permalink
Merge pull request #78 from simonsobs/dev
Browse files Browse the repository at this point in the history
Update tests and type hints
  • Loading branch information
TaiSakuma authored Jun 24, 2024
2 parents 49cfa3a + 2323ea6 commit 1ad795d
Show file tree
Hide file tree
Showing 26 changed files with 129 additions and 173 deletions.
9 changes: 7 additions & 2 deletions nextlinegraphql/custom/strawberry.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
5 changes: 3 additions & 2 deletions nextlinegraphql/factory.py
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
import contextlib
import logging.config
from collections.abc import AsyncIterator
from logging import getLogger
from typing import Any

Expand Down Expand Up @@ -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):
Expand All @@ -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/
Expand Down
7 changes: 5 additions & 2 deletions nextlinegraphql/hook/spec.py
Original file line number Diff line number Diff line change
@@ -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
Expand Down Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion nextlinegraphql/plugins/ctrl/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
40 changes: 26 additions & 14 deletions nextlinegraphql/plugins/ctrl/graphql/__init__.py
Original file line number Diff line number Diff line change
@@ -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')
102 changes: 0 additions & 102 deletions nextlinegraphql/plugins/ctrl/test.py

This file was deleted.

2 changes: 1 addition & 1 deletion nextlinegraphql/plugins/dev/plugin.py
Original file line number Diff line number Diff line change
Expand Up @@ -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)
14 changes: 13 additions & 1 deletion nextlinegraphql/plugins/graphql/graphql/__init__.py
Original file line number Diff line number Diff line change
@@ -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')
17 changes: 12 additions & 5 deletions nextlinegraphql/plugins/graphql/plugin.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -14,6 +14,9 @@

from .schema import Query

if TYPE_CHECKING:
from strawberry.asgi import Request, Response, WebSocket


class Plugin:
@spec.hookimpl
Expand All @@ -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

Expand Down Expand Up @@ -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
6 changes: 4 additions & 2 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -68,6 +68,7 @@ branch = true
source = ["nextlinegraphql", "tests"]
concurrency = ["multiprocessing"]
omit = [
"nextlinegraphql/plugins/ctrl/example_script/*",
"venv/*",
"*/site-packages/*",
]
Expand All @@ -81,6 +82,7 @@ exclude_lines = [
"raise NotImplementedError",
"if 0:",
'if __name__ == "__main__":',
"if TYPE_CHECKING:",
]
ignore_errors = true

Expand All @@ -98,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 = [
Expand Down
4 changes: 2 additions & 2 deletions tests/app/test_cors.py
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -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
Expand Down
10 changes: 6 additions & 4 deletions tests/dynaconf/merge/test_merge.py
Original file line number Diff line number Diff line change
Expand Up @@ -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/
Expand All @@ -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',
Expand All @@ -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
Expand All @@ -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
Expand Down
Loading

0 comments on commit 1ad795d

Please sign in to comment.