Skip to content

Commit

Permalink
Merge branch 'main' into feature/one-of
Browse files Browse the repository at this point in the history
  • Loading branch information
patrick91 committed May 21, 2024
2 parents 302d38f + fc322a8 commit 2dc1a07
Show file tree
Hide file tree
Showing 28 changed files with 843 additions and 168 deletions.
2 changes: 1 addition & 1 deletion .github/workflows/test.yml
Original file line number Diff line number Diff line change
Expand Up @@ -112,7 +112,7 @@ jobs:
if: steps.setup-python.outputs.cache-hit != 'true'

- name: Run benchmarks
uses: CodSpeedHQ/action@v1
uses: CodSpeedHQ/action@v2
with:
token: ${{ secrets.CODSPEED_TOKEN }}
run: poetry run pytest tests/benchmarks --codspeed
Expand Down
3 changes: 0 additions & 3 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,6 +1,3 @@
.DS_Store


# Created by https://www.gitignore.io/api/macos,linux,python,windows
# Edit at https://www.gitignore.io/?templates=macos,linux,python,windows

Expand Down
2 changes: 1 addition & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
repos:
- repo: https://github.com/astral-sh/ruff-pre-commit
rev: v0.4.1
rev: v0.4.4
hooks:
- id: ruff-format
exclude: ^tests/\w+/snapshots/
Expand Down
133 changes: 131 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,6 +1,135 @@
CHANGELOG
=========

0.229.1 - 2024-05-15
--------------------

This release fixes a regression from 0.229.0 where using a generic interface
inside a union would return an error.

Contributed by [Patrick Arminio](https://github.com/patrick91) via [PR #3502](https://github.com/strawberry-graphql/strawberry/pull/3502/)


0.229.0 - 2024-05-12
--------------------

This release improves our support for generic types, now using the same the same
generic multiple times with a list inside an interface or union is supported,
for example the following will work:

```python
import strawberry


@strawberry.type
class BlockRow[T]:
items: list[T]


@strawberry.type
class Query:
@strawberry.field
def blocks(self) -> list[BlockRow[str] | BlockRow[int]]:
return [
BlockRow(items=["a", "b", "c"]),
BlockRow(items=[1, 2, 3, 4]),
]


schema = strawberry.Schema(query=Query)
```

Contributed by [Patrick Arminio](https://github.com/patrick91) via [PR #3463](https://github.com/strawberry-graphql/strawberry/pull/3463/)


0.228.0 - 2024-05-12
--------------------

This releases updates the JSON scalar definition to have the updated `specifiedBy` URL.

The release is marked as minor because it will change the generated schema if you're using the JSON scalar.

Contributed by [Egor](https://github.com/Birdi7) via [PR #3478](https://github.com/strawberry-graphql/strawberry/pull/3478/)


0.227.7 - 2024-05-12
--------------------

This releases updates the `field-extensions` documentation's `StrawberryField` stability warning to include stable features.

The release is marked as patch because it only changes documentation.

Contributed by [Ray Sy](https://github.com/fireteam99) via [PR #3496](https://github.com/strawberry-graphql/strawberry/pull/3496/)


0.227.6 - 2024-05-11
--------------------

Fix `AssertionError` caused by the `DatadogTracingExtension` whenever the query is unavailable.

The bug in question was reported by issue [#3150](https://github.com/strawberry-graphql/strawberry/issues/3150).
The datadog extension would throw an `AssertionError` whenever there was no query available. This could happen if,
for example, a user POSTed something to `/graphql` with a JSON that doesn't contain a `query` field as per the
GraphQL spec.

The fix consists of adding `query_missing` to the `operation_type` tag, and also adding `query_missing` to the resource name.
It also makes it easier to look for logs of users making invalid queries by searching for `query_missing` in Datadog.

Contributed by [Lucas Valente](https://github.com/serramatutu) via [PR #3483](https://github.com/strawberry-graphql/strawberry/pull/3483/)


0.227.5 - 2024-05-11
--------------------

**Deprecations:** This release deprecates the `Starlite` integration in favour of the `LiteStar` integration.
Refer to the [LiteStar](./litestar.md) integration for more information.
LiteStar is a [renamed](https://litestar.dev/about/organization.html#litestar-and-starlite) and upgraded version of Starlite.

Before:

```python
from strawberry.starlite import make_graphql_controller
```

After:

```python
from strawberry.litestar import make_graphql_controller
```

Contributed by [Egor](https://github.com/Birdi7) via [PR #3492](https://github.com/strawberry-graphql/strawberry/pull/3492/)


0.227.4 - 2024-05-09
--------------------

This release fixes a bug in release 0.227.3 where FragmentSpread nodes
were not resolving edges.

Contributed by [Eric Uriostigue](https://github.com/euriostigue) via [PR #3487](https://github.com/strawberry-graphql/strawberry/pull/3487/)


0.227.3 - 2024-05-01
--------------------

This release adds an optimization to `ListConnection` such that only queries with
`edges` or `pageInfo` in their selected fields triggers `resolve_edges`.

This change is particularly useful for the `strawberry-django` extension's
`ListConnectionWithTotalCount` and the only selected field is `totalCount`. An
extraneous SQL query is prevented with this optimization.

Contributed by [Eric Uriostigue](https://github.com/euriostigue) via [PR #3480](https://github.com/strawberry-graphql/strawberry/pull/3480/)


0.227.2 - 2024-04-21
--------------------

This release fixes a minor issue where the docstring for the relay util `to_base64` described the return type incorrectly.

Contributed by [Gavin Bannerman](https://github.com/gbannerman) via [PR #3467](https://github.com/strawberry-graphql/strawberry/pull/3467/)


0.227.1 - 2024-04-20
--------------------

Expand Down Expand Up @@ -4633,11 +4762,11 @@ will print the following SDL:
directive @specifiedBy(name: String!) on SCALAR

"""
The `JSON` scalar type represents JSON values as specified by [ECMA-404](http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf).
The `JSON` scalar type represents JSON values as specified by [ECMA-404](https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf).
"""
scalar JSON
@specifiedBy(
url: "http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf"
url: "https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf"
)

type Query {
Expand Down
5 changes: 3 additions & 2 deletions docs/guides/field-extensions.md
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,9 @@ query {

<Warning>

The `StrawberryField` API is not stable and might change in the future without
warning.
Most of the `StrawberryField` API is not stable and might change in the future
without warning. Stable features include: `StrawberryField.type`,
`StrawberryField.python_name`, and `StrawberryField.arguments`.

</Warning>

Expand Down
10 changes: 10 additions & 0 deletions docs/integrations/starlite.md
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,16 @@ title: Starlite

# Starlite

## Deprecation Notice

This integration has been deprecated in favor of the `Litestar` integration.
Refer to the [Litestar](./litestar.md) integration for more information.
Litestar is a
[renamed](https://litestar.dev/about/organization.html#litestar-and-starlite)
and upgraded version of Starlite.

## How to use

Strawberry comes with an integration for
[Starlite](https://starliteproject.dev/) by providing a
`make_graphql_controller` function that can be used to create a GraphQL
Expand Down
7 changes: 7 additions & 0 deletions docs/types/scalars.md
Original file line number Diff line number Diff line change
Expand Up @@ -45,6 +45,13 @@ There are several built-in scalars, and you can define custom scalars too.
- `UUID`, a [UUID](https://docs.python.org/3/library/uuid.html#uuid.UUID) value
serialized as a string
- `Void`, always null, maps to Python鈥檚 `None`
- `JSON`, a JSON value as specified in
[ECMA-404](https://ecma-international.org/publications-and-standards/standards/ecma-404/)
standard, maps to Python鈥檚 `dict`
- `Base16`, `Base32`, `Base64`, represents hexadecimal strings encoded with
`Base16`/`Base32`/`Base64`. As specified in
[RFC4648](https://datatracker.ietf.org/doc/html/rfc4648.html). Maps to
Python鈥檚 `str`

Fields can return built-in scalars by using the Python equivalent:

Expand Down
2 changes: 1 addition & 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.227.1"
version = "0.229.1"
description = "A library for creating GraphQL APIs"
authors = ["Patrick Arminio <patrick.arminio@gmail.com>"]
license = "MIT"
Expand Down
1 change: 0 additions & 1 deletion strawberry/exceptions/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -44,7 +44,6 @@ def __init__(self, field_name: str, result_type: str) -> None:
super().__init__(message)


# TODO: this doesn't seem to be tested
class UnallowedReturnTypeForUnion(Exception):
"""The return type is not in the list of Union types"""

Expand Down
23 changes: 16 additions & 7 deletions strawberry/extensions/tracing/datadog.py
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,8 @@ def __init__(

@cached_property
def _resource_name(self) -> str:
assert self.execution_context.query
if self.execution_context.query is None:
return "query_missing"

query_hash = self.hash_query(self.execution_context.query)

Expand Down Expand Up @@ -78,15 +79,23 @@ def on_operation(self) -> Iterator[None]:
)
self.request_span.set_tag("graphql.operation_name", self._operation_name)

assert self.execution_context.query
query = self.execution_context.query

if query is not None:
query = query.strip()
operation_type = "query"

if query.startswith("mutation"):
operation_type = "mutation"
elif query.startswith("subscription"): # pragma: no cover
operation_type = "subscription"
else:
operation_type = "query_missing"

operation_type = "query"
if self.execution_context.query.strip().startswith("mutation"):
operation_type = "mutation"
elif self.execution_context.query.strip().startswith("subscription"):
operation_type = "subscription"
self.request_span.set_tag("graphql.operation_type", operation_type)

yield

self.request_span.finish()

def on_validate(self) -> Generator[None, None, None]:
Expand Down
13 changes: 12 additions & 1 deletion strawberry/relay/types.py
Original file line number Diff line number Diff line change
Expand Up @@ -38,7 +38,7 @@
from strawberry.utils.inspect import in_async_context
from strawberry.utils.typing import eval_type, is_classvar

from .utils import from_base64, to_base64
from .utils import from_base64, should_resolve_list_connection_edges, to_base64

if TYPE_CHECKING:
from strawberry.scalars import ID
Expand Down Expand Up @@ -933,6 +933,17 @@ async def resolver():
overfetch,
)

if not should_resolve_list_connection_edges(info):
return cls(
edges=[],
page_info=PageInfo(
start_cursor=None,
end_cursor=None,
has_previous_page=False,
has_next_page=False,
),
)

edges = [
edge_class.resolve_edge(
cls.resolve_node(v, info=info, **kwargs),
Expand Down
43 changes: 42 additions & 1 deletion strawberry/relay/utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,8 @@
from typing import Any, Tuple, Union
from typing_extensions import assert_never

from strawberry.types.info import Info
from strawberry.types.nodes import InlineFragment, Selection
from strawberry.types.types import StrawberryObjectDefinition


Expand Down Expand Up @@ -41,7 +43,7 @@ def to_base64(type_: Union[str, type, StrawberryObjectDefinition], node_id: Any)
The node id itself
Returns:
A tuple of (TypeName, NodeID).
A GlobalID, which is a string resulting from base64 encoding <TypeName>:<NodeID>.
Raises:
ValueError:
Expand All @@ -61,3 +63,42 @@ def to_base64(type_: Union[str, type, StrawberryObjectDefinition], node_id: Any)
raise ValueError(f"{type_} is not a valid GraphQL type or name") from e

return base64.b64encode(f"{type_name}:{node_id}".encode()).decode()


def should_resolve_list_connection_edges(info: Info) -> bool:
"""Check if the user requested to resolve the `edges` field of a connection.
Args:
info:
The strawberry execution info resolve the type name from
Returns:
True if the user requested to resolve the `edges` field of a connection, False otherwise.
"""
resolve_for_field_names = {"edges", "pageInfo"}

def _check_selection(selection: Selection) -> bool:
"""Recursively inspect the selection to check if the user requested to resolve the `edges` field.
Args:
selection (Selection): The selection to check.
Returns:
bool: True if the user requested to resolve the `edges` field of a connection, False otherwise.
"""
if (
not isinstance(selection, InlineFragment)
and selection.name in resolve_for_field_names
):
return True
if selection.selections:
return any(
_check_selection(selection) for selection in selection.selections
)
return False

for selection_field in info.selected_fields:
for selection in selection_field.selections:
if _check_selection(selection):
return True
return False
4 changes: 2 additions & 2 deletions strawberry/scalars.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@
description=(
"The `JSON` scalar type represents JSON values as specified by "
"[ECMA-404]"
"(http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf)."
"(https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf)."
),
specified_by_url=(
"http://www.ecma-international.org/publications/files/ECMA-ST/ECMA-404.pdf"
"https://ecma-international.org/wp-content/uploads/ECMA-404_2nd_edition_december_2017.pdf"
),
serialize=lambda v: v,
parse_value=lambda v: v,
Expand Down
Loading

0 comments on commit 2dc1a07

Please sign in to comment.