Skip to content

Commit

Permalink
Merge remote-tracking branch 'origin/main' into pydantic-v2-compat
Browse files Browse the repository at this point in the history
  • Loading branch information
thejaminator committed Jul 11, 2023
2 parents 590166d + a1dae33 commit 176dcbf
Show file tree
Hide file tree
Showing 12 changed files with 205 additions and 109 deletions.
18 changes: 18 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,24 @@
CHANGELOG
=========

0.194.4 - 2023-07-08
--------------------

This release makes sure that `Schema.process_errors()` is called _once_ for every error
which happens with `graphql-transport-ws` operations.

Contributed by [Kristján Valur Jónsson](https://github.com/kristjanvalur) via [PR #2899](https://github.com/strawberry-graphql/strawberry/pull/2899/)


0.194.3 - 2023-07-08
--------------------

Added default argument to the typer Argument function, this adds
support for older versions of typer.

Contributed by [Jaime Coello de Portugal](https://github.com/jaimecp89) via [PR #2906](https://github.com/strawberry-graphql/strawberry/pull/2906/)


0.194.2 - 2023-07-08
--------------------

Expand Down
24 changes: 24 additions & 0 deletions noxfile.py
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ def tests(session: Session) -> None:
"not django",
"-m",
"not starlite",
"-m",
"not pydantic",
"--ignore=tests/mypy",
"--ignore=tests/pyright",
)
Expand Down Expand Up @@ -88,6 +90,28 @@ def tests_litestar(session: Session) -> None:
)


@session(python=["3.11"], name="Pydantic tests", tags=["tests"])
# TODO: add pydantic 2.0 here :)
@nox.parametrize("pydantic", ["1.10"])
def test_pydantic(session: Session, pydantic: str) -> None:
session.run_always("poetry", "install", external=True)

session._session.install(f"pydantic~={pydantic}") # type: ignore

session.run(
"pytest",
"--cov=strawberry",
"--cov-append",
"--cov-report=xml",
"-n",
"auto",
"--showlocals",
"-vv",
"-m",
"pydantic",
)


@session(python=PYTHON_VERSIONS, name="Mypy tests")
def tests_mypy(session: Session) -> None:
session.run_always("poetry", "install", external=True)
Expand Down
12 changes: 6 additions & 6 deletions poetry.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 2 additions & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
[tool.poetry]
name = "strawberry-graphql"
packages = [ { include = "strawberry" } ]
version = "0.194.2"
version = "0.194.4"
description = "A library for creating GraphQL APIs"
authors = ["Patrick Arminio <patrick.arminio@gmail.com>"]
license = "MIT"
Expand Down Expand Up @@ -159,6 +159,7 @@ markers = [
"chalice",
"flask",
"starlite",
"pydantic",
"flaky",
"relay",
]
Expand Down
2 changes: 1 addition & 1 deletion strawberry/cli/commands/upgrade/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def upgrade(
autocompletion=lambda: list(codemods.keys()),
help="Name of the upgrade to run",
),
paths: List[pathlib.Path] = typer.Argument(file_okay=True, dir_okay=True),
paths: List[pathlib.Path] = typer.Argument(..., file_okay=True, dir_okay=True),
python_target: str = typer.Option(
".".join(str(x) for x in sys.version_info[:2]),
"--python-target",
Expand Down
2 changes: 1 addition & 1 deletion strawberry/field_extensions/input_mutation.py
Original file line number Diff line number Diff line change
Expand Up @@ -68,7 +68,7 @@ def resolve(
self,
next_: SyncExtensionResolver,
source: Any,
info: Info,
info: Info[Any, Any],
**kwargs: Any,
) -> Any:
input_args = kwargs.pop("input")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -248,6 +248,7 @@ async def get_result_source():

# Handle initial validation errors
if isinstance(result_source, GraphQLExecutionResult):
assert operation_type == OperationType.SUBSCRIPTION
assert result_source.errors
payload = [err.formatted for err in result_source.errors]
await self.send_message(ErrorMessage(id=message.id, payload=payload))
Expand Down Expand Up @@ -301,11 +302,13 @@ async def handle_async_results(
error_payload = [err.formatted for err in result.errors]
error_message = ErrorMessage(id=operation.id, payload=error_payload)
await operation.send_message(error_message)
self.schema.process_errors(result.errors)
# don't need to call schema.process_errors() here because
# it was already done by schema.execute()
return
else:
next_payload = {"data": result.data}
if result.errors:
self.schema.process_errors(result.errors)
next_payload["errors"] = [
err.formatted for err in result.errors
]
Expand Down
20 changes: 17 additions & 3 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -1,12 +1,26 @@
from typing import Tuple
import pathlib
from typing import List, Tuple

import pytest

def pytest_emoji_xfailed(config) -> Tuple[str, str]:

def pytest_emoji_xfailed(config: pytest.Config) -> Tuple[str, str]:
return "🤷‍♂️ ", "XFAIL 🤷‍♂️ "


def pytest_emoji_skipped(config) -> Tuple[str, str]:
def pytest_emoji_skipped(config: pytest.Config) -> Tuple[str, str]:
return "🦘 ", "SKIPPED 🦘"


pytest_plugins = ("tests.plugins.strawberry_exceptions",)


@pytest.hookimpl # type: ignore
def pytest_collection_modifyitems(config: pytest.Config, items: List[pytest.Item]):
rootdir = pathlib.Path(config.rootdir) # type: ignore

for item in items:
rel_path = pathlib.Path(item.fspath).relative_to(rootdir)

if "pydantic" in rel_path.parts:
item.add_marker(pytest.mark.pydantic)
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,6 @@
import strawberry
from strawberry.field_extensions import InputMutationExtension
from strawberry.schema_directive import Location, schema_directive
from strawberry.types import Info


@schema_directive(
Expand All @@ -24,10 +23,16 @@ class Fruit:

@strawberry.type
class Query:
@strawberry.field
def hello(self) -> str:
return "hi"


@strawberry.type
class Mutation:
@strawberry.mutation(extensions=[InputMutationExtension()])
def create_fruit(
self,
info: Info,
name: str,
color: Annotated[
str,
Expand All @@ -45,7 +50,6 @@ def create_fruit(
@strawberry.mutation(extensions=[InputMutationExtension()])
async def create_fruit_async(
self,
info: Info,
name: str,
color: Annotated[str, object()],
) -> Fruit:
Expand All @@ -55,7 +59,7 @@ async def create_fruit_async(
)


schema = strawberry.Schema(query=Query)
schema = strawberry.Schema(query=Query, mutation=Mutation)


def test_schema():
Expand All @@ -79,7 +83,7 @@ def test_schema():
color: String!
}
type Query {
type Mutation {
createFruit(
"""Input data for `createFruit` mutation"""
input: CreateFruitInput!
Expand All @@ -89,14 +93,18 @@ def test_schema():
input: CreateFruitAsyncInput!
): Fruit!
}
type Query {
hello: String!
}
'''
assert str(schema).strip() == textwrap.dedent(expected).strip()


def test_input_mutation():
result = schema.execute_sync(
"""
query TestQuery ($input: CreateFruitInput!) {
mutation TestQuery ($input: CreateFruitInput!) {
createFruit (input: $input) {
... on Fruit {
name
Expand Down Expand Up @@ -124,7 +132,7 @@ def test_input_mutation():
async def test_input_mutation_async():
result = await schema.execute(
"""
query TestQuery ($input: CreateFruitAsyncInput!) {
mutation TestQuery ($input: CreateFruitAsyncInput!) {
createFruitAsync (input: $input) {
... on Fruit {
name
Expand Down
3 changes: 3 additions & 0 deletions tests/schema/test_pydantic.py
Original file line number Diff line number Diff line change
@@ -1,7 +1,10 @@
import pytest
from pydantic import BaseModel, Field

import strawberry

pytestmark = pytest.mark.pydantic


def test_use_alias_as_gql_name():
class UserModel(BaseModel):
Expand Down
14 changes: 12 additions & 2 deletions tests/views/schema.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@
from strawberry.file_uploads import Upload
from strawberry.permission import BasePermission
from strawberry.subscriptions.protocols.graphql_transport_ws.types import PingMessage
from strawberry.types import Info
from strawberry.types import ExecutionContext, Info


class AlwaysFailPermission(BasePermission):
Expand Down Expand Up @@ -262,7 +262,17 @@ async def long_finalizer(
await asyncio.sleep(delay)


schema = strawberry.Schema(
class Schema(strawberry.Schema):
def process_errors(
self, errors: List, execution_context: Optional[ExecutionContext] = None
) -> None:
import traceback

traceback.print_stack()
return super().process_errors(errors, execution_context)


schema = Schema(
query=Query,
mutation=Mutation,
subscription=Subscription,
Expand Down
Loading

0 comments on commit 176dcbf

Please sign in to comment.