diff --git a/strawberry/experimental/pydantic/error_type.py b/strawberry/experimental/pydantic/error_type.py index 21e56c9b0d..1f87778697 100644 --- a/strawberry/experimental/pydantic/error_type.py +++ b/strawberry/experimental/pydantic/error_type.py @@ -33,6 +33,8 @@ if TYPE_CHECKING: from collections.abc import Sequence + from strawberry.types.base import WithStrawberryObjectDefinition + def get_type_for_field(field: CompatModelField) -> Union[type[Union[None, list]], Any]: type_ = field.outer_type_ @@ -113,7 +115,7 @@ def wrap(cls: type) -> type: if name in fields_set ] - wrapped = _wrap_dataclass(cls) + wrapped: type[WithStrawberryObjectDefinition] = _wrap_dataclass(cls) extra_fields = cast(list[dataclasses.Field], _get_fields(wrapped, {})) private_fields = get_private_fields(wrapped) @@ -146,7 +148,7 @@ def wrap(cls: type) -> type: ) model._strawberry_type = cls # type: ignore[attr-defined] - cls._pydantic_type = model + cls._pydantic_type = model # type: ignore[attr-defined] return cls return wrap diff --git a/strawberry/experimental/pydantic/fields.py b/strawberry/experimental/pydantic/fields.py index 83841f9128..fe6b863431 100644 --- a/strawberry/experimental/pydantic/fields.py +++ b/strawberry/experimental/pydantic/fields.py @@ -24,14 +24,7 @@ else: raise -try: - from typing import GenericAlias as TypingGenericAlias # type: ignore -except ImportError: - import sys - - # python < 3.9 does not have GenericAlias (list[int], tuple[str, ...] and so on) - # we do this under a conditional to avoid a mypy :) - raise +from typing import GenericAlias as TypingGenericAlias # type: ignore def replace_pydantic_types(type_: Any, is_input: bool) -> Any: diff --git a/strawberry/ext/mypy_plugin.py b/strawberry/ext/mypy_plugin.py index c379b56997..797428019f 100644 --- a/strawberry/ext/mypy_plugin.py +++ b/strawberry/ext/mypy_plugin.py @@ -104,7 +104,7 @@ def __str__(self) -> str: return self.message -def lazy_type_analyze_callback(ctx: AnalyzeTypeContext) -> type: +def lazy_type_analyze_callback(ctx: AnalyzeTypeContext) -> Type: if len(ctx.type.args) == 0: # TODO: maybe this should throw an error @@ -123,7 +123,7 @@ def _get_named_type(name: str, api: SemanticAnalyzerPluginInterface) -> Any: return api.named_type(name) -def _get_type_for_expr(expr: Expression, api: SemanticAnalyzerPluginInterface) -> type: +def _get_type_for_expr(expr: Expression, api: SemanticAnalyzerPluginInterface) -> Type: if isinstance(expr, NameExpr): # guarding against invalid nodes, still have to figure out why this happens # but sometimes mypy crashes because the internal node of the named type @@ -247,7 +247,7 @@ def enum_hook(ctx: DynamicClassDefContext) -> None: ) return - enum_type: Optional[type] + enum_type: Optional[Type] try: enum_type = _get_type_for_expr(first_argument, ctx.api) @@ -295,7 +295,7 @@ def scalar_hook(ctx: DynamicClassDefContext) -> None: ) return - scalar_type: Optional[type] + scalar_type: Optional[Type] # TODO: add proper support for NewType @@ -620,7 +620,7 @@ def _is_strawberry_pydantic_decorator(self, fullname: str) -> bool: ) -def plugin(version: str) -> typing.type[StrawberryPlugin]: +def plugin(version: str) -> typing.Type[StrawberryPlugin]: match = VERSION_RE.match(version) if match: MypyVersion.VERSION = Decimal(".".join(match.groups())) diff --git a/strawberry/federation/object_type.py b/strawberry/federation/object_type.py index 689e005d09..e31f3d2cae 100644 --- a/strawberry/federation/object_type.py +++ b/strawberry/federation/object_type.py @@ -1,3 +1,4 @@ +import builtins from collections.abc import Iterable, Sequence from typing import ( TYPE_CHECKING, @@ -20,7 +21,7 @@ from .schema_directives import Key -T = TypeVar("T", bound=type) +T = TypeVar("T", bound=builtins.type) def _impl_type( diff --git a/strawberry/federation/schema_directive.py b/strawberry/federation/schema_directive.py index 1c0fb50cf5..6ff9138e83 100644 --- a/strawberry/federation/schema_directive.py +++ b/strawberry/federation/schema_directive.py @@ -36,12 +36,12 @@ def schema_directive( print_definition: bool = True, compose: bool = False, import_url: Optional[str] = None, -) -> Callable[..., T]: +) -> Callable[[T], T]: def _wrap(cls: T) -> T: cls = _wrap_dataclass(cls) # type: ignore fields = _get_fields(cls, {}) - cls.__strawberry_directive__ = StrawberryFederationSchemaDirective( + cls.__strawberry_directive__ = StrawberryFederationSchemaDirective( # type: ignore[attr-defined] python_name=cls.__name__, graphql_name=name, locations=locations, diff --git a/strawberry/printer/printer.py b/strawberry/printer/printer.py index 1116ce25de..d51ae32a2c 100644 --- a/strawberry/printer/printer.py +++ b/strawberry/printer/printer.py @@ -12,7 +12,7 @@ overload, ) -from graphql import is_union_type +from graphql import GraphQLObjectType, GraphQLSchema, is_union_type from graphql.language.printer import print_ast from graphql.type import ( is_enum_type, @@ -33,7 +33,11 @@ from graphql.utilities.print_schema import print_type as original_print_type from strawberry.schema_directive import Location, StrawberrySchemaDirective -from strawberry.types.base import StrawberryContainer, has_object_definition +from strawberry.types.base import ( + StrawberryContainer, + StrawberryObjectDefinition, + has_object_definition, +) from strawberry.types.enum import EnumDefinition from strawberry.types.scalar import ScalarWrapper from strawberry.types.unset import UNSET @@ -220,7 +224,12 @@ def print_args( ) -def print_fields(type_: type, schema: BaseSchema, *, extras: PrintExtras) -> str: +def print_fields( + type_: GraphQLObjectType, + schema: BaseSchema, + *, + extras: PrintExtras, +) -> str: from strawberry.schema.schema_converter import GraphQLCoreConverter fields = [] @@ -315,11 +324,13 @@ def print_enum( ) -def print_extends(type_: type, schema: BaseSchema) -> str: +def print_extends(type_: GraphQLObjectType, schema: BaseSchema) -> str: from strawberry.schema.schema_converter import GraphQLCoreConverter - strawberry_type = type_.extensions and type_.extensions.get( - GraphQLCoreConverter.DEFINITION_BACKREF + strawberry_type = cast( + Optional[StrawberryObjectDefinition], + type_.extensions + and type_.extensions.get(GraphQLCoreConverter.DEFINITION_BACKREF), ) if strawberry_type and strawberry_type.extend: @@ -329,12 +340,14 @@ def print_extends(type_: type, schema: BaseSchema) -> str: def print_type_directives( - type_: type, schema: BaseSchema, *, extras: PrintExtras + type_: GraphQLObjectType, schema: BaseSchema, *, extras: PrintExtras ) -> str: from strawberry.schema.schema_converter import GraphQLCoreConverter - strawberry_type = type_.extensions and type_.extensions.get( - GraphQLCoreConverter.DEFINITION_BACKREF + strawberry_type = cast( + Optional[StrawberryObjectDefinition], + type_.extensions + and type_.extensions.get(GraphQLCoreConverter.DEFINITION_BACKREF), ) if not strawberry_type: @@ -349,7 +362,7 @@ def print_type_directives( for directive in strawberry_type.directives or [] if any( location in allowed_locations - for location in directive.__strawberry_directive__.locations + for location in directive.__strawberry_directive__.locations # type: ignore[attr-defined] ) ) @@ -545,21 +558,33 @@ def is_builtin_directive(directive: GraphQLDirective) -> bool: def print_schema(schema: BaseSchema) -> str: - graphql_core_schema = schema._schema # type: ignore + graphql_core_schema = cast( + GraphQLSchema, + schema._schema, # type: ignore + ) extras = PrintExtras() - directives = filter( - lambda n: not is_builtin_directive(n), graphql_core_schema.directives - ) + filtered_directives = [ + directive + for directive in graphql_core_schema.directives + if not is_builtin_directive(directive) + ] + type_map = graphql_core_schema.type_map - types = filter(is_defined_type, map(type_map.get, sorted(type_map))) + types = [ + type_ + for type_name in sorted(type_map) + if is_defined_type(type_ := type_map[type_name]) + ] types_printed = [_print_type(type_, schema, extras=extras) for type_ in types] schema_definition = print_schema_definition(schema, extras=extras) - directives = filter( - None, [print_directive(directive, schema=schema) for directive in directives] - ) + directives = [ + printed_directive + for directive in filtered_directives + if (printed_directive := print_directive(directive, schema=schema)) is not None + ] def _name_getter(type_: Any) -> str: if hasattr(type_, "name"): diff --git a/strawberry/schema/base.py b/strawberry/schema/base.py index 25751cf282..cc580f12c5 100644 --- a/strawberry/schema/base.py +++ b/strawberry/schema/base.py @@ -18,7 +18,10 @@ ExecutionContext, ExecutionResult, ) - from strawberry.types.base import StrawberryObjectDefinition + from strawberry.types.base import ( + StrawberryObjectDefinition, + WithStrawberryObjectDefinition, + ) from strawberry.types.enum import EnumDefinition from strawberry.types.graphql import OperationType from strawberry.types.scalar import ScalarDefinition @@ -31,9 +34,9 @@ class BaseSchema(Protocol): config: StrawberryConfig schema_converter: GraphQLCoreConverter - query: type - mutation: Optional[type] - subscription: Optional[type] + query: type[WithStrawberryObjectDefinition] + mutation: Optional[type[WithStrawberryObjectDefinition]] + subscription: Optional[type[WithStrawberryObjectDefinition]] schema_directives: list[object] @abstractmethod diff --git a/strawberry/schema/schema.py b/strawberry/schema/schema.py index 5bd676d663..2351c8d51b 100644 --- a/strawberry/schema/schema.py +++ b/strawberry/schema/schema.py @@ -33,7 +33,11 @@ from strawberry.schema.schema_converter import GraphQLCoreConverter from strawberry.schema.types.scalar import DEFAULT_SCALAR_REGISTRY from strawberry.types import ExecutionContext -from strawberry.types.base import StrawberryObjectDefinition, has_object_definition +from strawberry.types.base import ( + StrawberryObjectDefinition, + WithStrawberryObjectDefinition, + has_object_definition, +) from strawberry.types.graphql import OperationType from ..printer import print_schema @@ -140,14 +144,24 @@ class Query: self.directives = directives self.schema_directives = list(schema_directives) - query_type = self.schema_converter.from_object(query.__strawberry_definition__) + query_type = self.schema_converter.from_object( + cast(type[WithStrawberryObjectDefinition], query).__strawberry_definition__ + ) mutation_type = ( - self.schema_converter.from_object(mutation.__strawberry_definition__) + self.schema_converter.from_object( + cast( + type[WithStrawberryObjectDefinition], mutation + ).__strawberry_definition__ + ) if mutation else None ) subscription_type = ( - self.schema_converter.from_object(subscription.__strawberry_definition__) + self.schema_converter.from_object( + cast( + type[WithStrawberryObjectDefinition], subscription + ).__strawberry_definition__ + ) if subscription else None ) diff --git a/strawberry/schema/schema_converter.py b/strawberry/schema/schema_converter.py index 811baab951..bc364ef219 100644 --- a/strawberry/schema/schema_converter.py +++ b/strawberry/schema/schema_converter.py @@ -328,7 +328,8 @@ def from_directive(self, directive: StrawberryDirective) -> GraphQLDirective: def from_schema_directive(self, cls: type) -> GraphQLDirective: strawberry_directive = cast( - "StrawberrySchemaDirective", cls.__strawberry_directive__ + "StrawberrySchemaDirective", + cls.__strawberry_directive__, # type: ignore[attr-defined] ) module = sys.modules[cls.__module__] @@ -770,7 +771,7 @@ def from_scalar(self, scalar: type) -> GraphQLScalarType: else: scalar_definition = _scalar_definition else: - scalar_definition = scalar._scalar_definition + scalar_definition = scalar._scalar_definition # type: ignore[attr-defined] scalar_name = self.config.name_converter.from_type(scalar_definition) diff --git a/strawberry/schema/types/scalar.py b/strawberry/schema/types/scalar.py index 47f623640a..d07c55b886 100644 --- a/strawberry/schema/types/scalar.py +++ b/strawberry/schema/types/scalar.py @@ -45,7 +45,7 @@ def _make_scalar_definition(scalar_type: GraphQLScalarType) -> ScalarDefinition: def _get_scalar_definition(scalar: type) -> ScalarDefinition: - return scalar._scalar_definition + return scalar._scalar_definition # type: ignore[attr-defined] DEFAULT_SCALAR_REGISTRY: dict[object, ScalarDefinition] = { diff --git a/strawberry/schema_directive.py b/strawberry/schema_directive.py index b7376c3900..6cf5069a11 100644 --- a/strawberry/schema_directive.py +++ b/strawberry/schema_directive.py @@ -51,12 +51,12 @@ def schema_directive( name: Optional[str] = None, repeatable: bool = False, print_definition: bool = True, -) -> Callable[..., T]: +) -> Callable[[T], T]: def _wrap(cls: T) -> T: cls = _wrap_dataclass(cls) # type: ignore fields = _get_fields(cls, {}) - cls.__strawberry_directive__ = StrawberrySchemaDirective( + cls.__strawberry_directive__ = StrawberrySchemaDirective( # type: ignore[attr-defined] python_name=cls.__name__, graphql_name=name, locations=locations, diff --git a/strawberry/types/object_type.py b/strawberry/types/object_type.py index 252540eb06..8160c79f6f 100644 --- a/strawberry/types/object_type.py +++ b/strawberry/types/object_type.py @@ -1,3 +1,4 @@ +import builtins import dataclasses import inspect import sys @@ -26,10 +27,10 @@ from .field import StrawberryField, field from .type_resolver import _get_fields -T = TypeVar("T", bound=type) +T = TypeVar("T", bound=builtins.type) -def _get_interfaces(cls: type[Any]) -> list[StrawberryObjectDefinition]: +def _get_interfaces(cls: builtins.type[Any]) -> list[StrawberryObjectDefinition]: interfaces: list[StrawberryObjectDefinition] = [] for base in cls.__mro__[1:]: # Exclude current class type_definition = get_object_definition(base) @@ -39,7 +40,7 @@ def _get_interfaces(cls: type[Any]) -> list[StrawberryObjectDefinition]: return interfaces -def _check_field_annotations(cls: type[Any]) -> None: +def _check_field_annotations(cls: builtins.type[Any]) -> None: """Are any of the dataclass Fields missing type annotations? This is similar to the check that dataclasses do during creation, but allows us to @@ -97,7 +98,7 @@ def _check_field_annotations(cls: type[Any]) -> None: raise MissingFieldAnnotationError(field_name, cls) -def _wrap_dataclass(cls: type[T]) -> type[T]: +def _wrap_dataclass(cls: builtins.type[T]) -> builtins.type[T]: """Wrap a strawberry.type class with a dataclass and check for any issues before doing so.""" # Ensure all Fields have been properly type-annotated _check_field_annotations(cls) @@ -140,7 +141,7 @@ def _process_type( is_type_of = getattr(cls, "is_type_of", None) resolve_type = getattr(cls, "resolve_type", None) - cls.__strawberry_definition__ = StrawberryObjectDefinition( + cls.__strawberry_definition__ = StrawberryObjectDefinition( # type: ignore[attr-defined] name=name, is_input=is_input, is_interface=is_interface, @@ -156,7 +157,7 @@ def _process_type( # TODO: remove when deprecating _type_definition DeprecatedDescriptor( DEPRECATION_MESSAGES._TYPE_DEFINITION, - cls.__strawberry_definition__, + cls.__strawberry_definition__, # type: ignore[attr-defined] "_type_definition", ).inject(cls) diff --git a/strawberry/utils/typing.py b/strawberry/utils/typing.py index 1bee437276..c41bfb684c 100644 --- a/strawberry/utils/typing.py +++ b/strawberry/utils/typing.py @@ -109,14 +109,14 @@ def is_optional(annotation: type) -> bool: if not is_union(annotation): return False - types = annotation.__args__ + types = annotation.__args__ # type: ignore[attr-defined] # A Union to be optional needs to have at least one None type return any(x == None.__class__ for x in types) def get_optional_annotation(annotation: type) -> type: - types = annotation.__args__ + types = annotation.__args__ # type: ignore[attr-defined] non_none_types = tuple(x for x in types if x != None.__class__) @@ -124,13 +124,13 @@ def get_optional_annotation(annotation: type) -> type: # type (normally a Union type). if len(non_none_types) > 1: - return annotation.copy_with(non_none_types) + return annotation.copy_with(non_none_types) # type: ignore[attr-defined] return non_none_types[0] def get_list_annotation(annotation: type) -> type: - return annotation.__args__[0] + return annotation.__args__[0] # type: ignore[attr-defined] def is_concrete_generic(annotation: type) -> bool: @@ -197,7 +197,7 @@ def get_parameters(annotation: type) -> Union[tuple[object], tuple[()]]: and issubclass(annotation, Generic) # type:ignore and annotation is not Generic ): - return annotation.__parameters__ + return annotation.__parameters__ # type: ignore[union-attr] else: return () # pragma: no cover diff --git a/tests/experimental/pydantic/schema/test_federation.py b/tests/experimental/pydantic/schema/test_federation.py index 47bd56c2f9..db94a8e336 100644 --- a/tests/experimental/pydantic/schema/test_federation.py +++ b/tests/experimental/pydantic/schema/test_federation.py @@ -26,7 +26,7 @@ def resolve_reference(cls, upc) -> "Product": @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/experimental/pydantic/schema/test_federation.py-E b/tests/experimental/pydantic/schema/test_federation.py-E deleted file mode 100644 index fe2efa34f3..0000000000 --- a/tests/experimental/pydantic/schema/test_federation.py-E +++ /dev/null @@ -1,53 +0,0 @@ -import typing - -from pydantic import BaseModel - -import strawberry -from strawberry.federation.schema_directives import Key - - -def test_fetch_entities_pydantic(): - class ProductInDb(BaseModel): - upc: str - name: str - - # @strawberry.federation.type(keys=["upc"]) - @strawberry.experimental.pydantic.type( - model=ProductInDb, directives=[Key(fields="upc", resolvable=True)] - ) - class Product: - upc: str - name: str - - @classmethod - def resolve_reference(cls, upc) -> "Product": - return Product(upc=upc, name="") - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.list[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [{"__typename": "Product", "upc": "B00005N5PF"}] - }, - ) - - assert not result.errors - - assert result.data == {"_entities": [{"upc": "B00005N5PF"}]} diff --git a/tests/federation/printer/test_authenticated.py b/tests/federation/printer/test_authenticated.py index 35f598afd8..d362dad337 100644 --- a/tests/federation/printer/test_authenticated.py +++ b/tests/federation/printer/test_authenticated.py @@ -19,7 +19,7 @@ class Query: @strawberry.federation.field(authenticated=True) def top_products( self, first: Annotated[int, strawberry.federation.argument()] - ) -> list[Product]: + ) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_entities.py b/tests/federation/printer/test_entities.py index 64e8a3b094..7f7ada547b 100644 --- a/tests/federation/printer/test_entities.py +++ b/tests/federation/printer/test_entities.py @@ -26,7 +26,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -89,7 +89,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_inaccessible.py b/tests/federation/printer/test_inaccessible.py index 3f9f5da399..110ec1075d 100644 --- a/tests/federation/printer/test_inaccessible.py +++ b/tests/federation/printer/test_inaccessible.py @@ -33,7 +33,7 @@ class Query: def top_products( self, first: Annotated[int, strawberry.federation.argument(inaccessible=True)], - ) -> list[Product]: + ) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema( @@ -96,7 +96,7 @@ class Query: @strawberry.type class Mutation: @strawberry.federation.mutation(inaccessible=True) - def hello(self) -> str: + def hello(self) -> str: # pragma: no cover return "Hello" schema = strawberry.federation.Schema( diff --git a/tests/federation/printer/test_interface.py b/tests/federation/printer/test_interface.py index c77cc2875c..3d96fa0906 100644 --- a/tests/federation/printer/test_interface.py +++ b/tests/federation/printer/test_interface.py @@ -15,7 +15,7 @@ class Product(SomeInterface): @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_keys.py b/tests/federation/printer/test_keys.py index ccaf707025..e6368b24b4 100644 --- a/tests/federation/printer/test_keys.py +++ b/tests/federation/printer/test_keys.py @@ -27,7 +27,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=False) @@ -89,7 +89,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_override.py b/tests/federation/printer/test_override.py index b9d04d7f26..a5682b88fd 100644 --- a/tests/federation/printer/test_override.py +++ b/tests/federation/printer/test_override.py @@ -18,7 +18,7 @@ class Product(SomeInterface): @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -70,7 +70,7 @@ class Product(SomeInterface): @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_policy.py b/tests/federation/printer/test_policy.py index 9865aead51..043eafc5a5 100644 --- a/tests/federation/printer/test_policy.py +++ b/tests/federation/printer/test_policy.py @@ -25,7 +25,7 @@ class Query: ) def top_products( self, first: Annotated[int, strawberry.federation.argument()] - ) -> list[Product]: + ) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_provides.py b/tests/federation/printer/test_provides.py index 328bc48816..87c8c6970e 100644 --- a/tests/federation/printer/test_provides.py +++ b/tests/federation/printer/test_provides.py @@ -28,7 +28,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema( @@ -100,7 +100,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema( diff --git a/tests/federation/printer/test_requires.py b/tests/federation/printer/test_requires.py index e8367d4a2c..8abdfb2ddf 100644 --- a/tests/federation/printer/test_requires.py +++ b/tests/federation/printer/test_requires.py @@ -32,7 +32,7 @@ class Review: @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_requires_scopes.py b/tests/federation/printer/test_requires_scopes.py index bf6a772097..3e87487a12 100644 --- a/tests/federation/printer/test_requires_scopes.py +++ b/tests/federation/printer/test_requires_scopes.py @@ -25,7 +25,7 @@ class Query: ) def top_products( self, first: Annotated[int, strawberry.federation.argument()] - ) -> list[Product]: + ) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_shareable.py b/tests/federation/printer/test_shareable.py index 9f85da1215..820d21819d 100644 --- a/tests/federation/printer/test_shareable.py +++ b/tests/federation/printer/test_shareable.py @@ -17,7 +17,7 @@ class Product(SomeInterface): @strawberry.federation.type class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/printer/test_tag.py b/tests/federation/printer/test_tag.py index b97f368253..f485f16524 100644 --- a/tests/federation/printer/test_tag.py +++ b/tests/federation/printer/test_tag.py @@ -21,7 +21,7 @@ class Query: @strawberry.field def top_products( self, first: Annotated[int, strawberry.federation.argument(tags=["myTag"])] - ) -> list[Product]: + ) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/test_entities.py b/tests/federation/test_entities.py index ad79aeade8..73d9d1d102 100644 --- a/tests/federation/test_entities.py +++ b/tests/federation/test_entities.py @@ -18,7 +18,7 @@ def resolve_reference(cls, upc) -> "Product": @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -58,7 +58,7 @@ def resolve_reference(cls, info: strawberry.Info, upc: str) -> "Product": @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -102,7 +102,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -142,7 +142,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -189,7 +189,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -232,7 +232,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -430,7 +430,7 @@ async def resolve_reference(cls, upc: str) -> "Product": @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -469,7 +469,7 @@ async def resolve_reference(cls, upc: str) -> "Product": @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: + def top_products(self, first: int) -> typing.List[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) diff --git a/tests/federation/test_entities.py-E b/tests/federation/test_entities.py-E deleted file mode 100644 index b18a8c3b7d..0000000000 --- a/tests/federation/test_entities.py-E +++ /dev/null @@ -1,499 +0,0 @@ -import typing - -from graphql import located_error - -import strawberry -from strawberry.types import Info - - -def test_fetch_entities(): - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - - @classmethod - def resolve_reference(cls, upc) -> "Product": - return Product(upc=upc) - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [{"__typename": "Product", "upc": "B00005N5PF"}] - }, - ) - - assert not result.errors - - assert result.data == {"_entities": [{"upc": "B00005N5PF"}]} - - -def test_info_param_in_resolve_reference(): - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - debug_field_name: str - - @classmethod - def resolve_reference(cls, info: strawberry.Info, upc: str) -> "Product": - return Product(upc=upc, debug_field_name=info.field_name) - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - debugFieldName - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [{"__typename": "Product", "upc": "B00005N5PF"}] - }, - ) - - assert not result.errors - - assert result.data == { - "_entities": [ - { - "upc": "B00005N5PF", - # _entities is the field that's called by federation - "debugFieldName": "_entities", - } - ] - } - - -def test_does_not_need_custom_resolve_reference_for_basic_things(): - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [{"__typename": "Product", "upc": "B00005N5PF"}] - }, - ) - - assert not result.errors - - assert result.data == {"_entities": [{"upc": "B00005N5PF"}]} - - -def test_does_not_need_custom_resolve_reference_nested(): - @strawberry.federation.type(keys=["id"]) - class Something: - id: str - - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - something: Something - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - something { - id - } - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [ - {"__typename": "Product", "upc": "B00005N5PF", "something": {"id": "1"}} - ] - }, - ) - - assert not result.errors - - assert result.data == { - "_entities": [{"upc": "B00005N5PF", "something": {"id": "1"}}] - } - - -def test_fails_properly_when_wrong_key_is_passed(): - @strawberry.type - class Something: - id: str - - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - something: Something - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - something { - id - } - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [{"__typename": "Product", "not_upc": "B00005N5PF"}] - }, - ) - - assert result.errors - - assert result.errors[0].message == "Unable to resolve reference for Product" - - -def test_fails_properly_when_wrong_data_is_passed(): - @strawberry.federation.type(keys=["id"]) - class Something: - id: str - - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - something: Something - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - something { - id - } - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [ - { - "__typename": "Product", - "upc": "B00005N5PF", - "not_something": {"id": "1"}, - } - ] - }, - ) - - assert result.errors - - assert result.errors[0].message == "Unable to resolve reference for Product" - - -def test_propagates_original_error_message_with_auto_graphql_error_metadata(): - @strawberry.federation.type(keys=["id"]) - class Product: - id: strawberry.ID - - @classmethod - def resolve_reference(cls, id: strawberry.ID) -> "Product": - raise Exception("Foo bar") - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def mock(self) -> typing.Optional[Product]: - return None - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - id - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [ - { - "__typename": "Product", - "id": "B00005N5PF", - } - ] - }, - ) - - assert len(result.errors) == 1 - error = result.errors[0].formatted - assert error["message"] == "Foo bar" - assert error["path"] == ["_entities", 0] - assert error["locations"] == [{"column": 13, "line": 3}] - assert "extensions" not in error - - -def test_propagates_custom_type_error_message_with_auto_graphql_error_metadata(): - class MyTypeError(TypeError): - pass - - @strawberry.federation.type(keys=["id"]) - class Product: - id: strawberry.ID - - @classmethod - def resolve_reference(cls, id: strawberry.ID) -> "Product": - raise MyTypeError("Foo bar") - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def mock(self) -> typing.Optional[Product]: - return None - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - id - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [ - { - "__typename": "Product", - "id": "B00005N5PF", - } - ] - }, - ) - - assert len(result.errors) == 1 - error = result.errors[0].formatted - assert error["message"] == "Foo bar" - assert error["path"] == ["_entities", 0] - assert error["locations"] == [{"column": 13, "line": 3}] - assert "extensions" not in error - - -def test_propagates_original_error_message_and_graphql_error_metadata(): - @strawberry.federation.type(keys=["id"]) - class Product: - id: strawberry.ID - - @classmethod - def resolve_reference(cls, info: Info, id: strawberry.ID) -> "Product": - exception = Exception("Foo bar") - exception.extensions = {"baz": "qux"} - raise located_error( - exception, - nodes=info._raw_info.field_nodes[0], - path=["_entities_override", 0], - ) - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def mock(self) -> typing.Optional[Product]: - return None - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - id - } - } - } - """ - - result = schema.execute_sync( - query, - variable_values={ - "representations": [ - { - "__typename": "Product", - "id": "B00005N5PF", - } - ] - }, - ) - - assert len(result.errors) == 1 - error = result.errors[0].formatted - assert error["message"] == "Foo bar" - assert error["path"] == ["_entities_override", 0] - assert error["locations"] == [{"column": 13, "line": 3}] - assert error["extensions"] == {"baz": "qux"} - - -async def test_can_use_async_resolve_reference(): - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - - @classmethod - async def resolve_reference(cls, upc: str) -> "Product": - return Product(upc=upc) - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.List[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - } - } - } - """ - - result = await schema.execute( - query, - variable_values={ - "representations": [{"__typename": "Product", "upc": "B00005N5PF"}] - }, - ) - - assert not result.errors - - assert result.data == {"_entities": [{"upc": "B00005N5PF"}]} - - -async def test_can_use_async_resolve_reference_multiple_representations(): - @strawberry.federation.type(keys=["upc"]) - class Product: - upc: str - - @classmethod - async def resolve_reference(cls, upc: str) -> "Product": - return Product(upc=upc) - - @strawberry.federation.type(extend=True) - class Query: - @strawberry.field - def top_products(self, first: int) -> typing.list[Product]: - return [] - - schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) - - query = """ - query ($representations: [_Any!]!) { - _entities(representations: $representations) { - ... on Product { - upc - } - } - } - """ - - result = await schema.execute( - query, - variable_values={ - "representations": [ - {"__typename": "Product", "upc": "B00005N5PF"}, - {"__typename": "Product", "upc": "B00005N5PG"}, - ] - }, - ) - - assert not result.errors - - assert result.data == {"_entities": [{"upc": "B00005N5PF"}, {"upc": "B00005N5PG"}]} diff --git a/tests/federation/test_schema.py b/tests/federation/test_schema.py index 123de4b1a5..278d691a52 100644 --- a/tests/federation/test_schema.py +++ b/tests/federation/test_schema.py @@ -18,7 +18,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -74,7 +74,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -136,7 +136,7 @@ class Example: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> list[Example]: + def top_products(self, first: int) -> list[Example]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -164,7 +164,7 @@ class Product: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> list[Product]: + def top_products(self, first: int) -> list[Product]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -215,7 +215,9 @@ class ListOfProducts(Generic[T]): @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, first: int) -> ListOfProducts[Product]: + def top_products( + self, first: int + ) -> ListOfProducts[Product]: # pragma: no cover return ListOfProducts(products=[]) schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -264,7 +266,7 @@ class ExampleInput: @strawberry.federation.type(extend=True) class Query: @strawberry.field - def top_products(self, example: ExampleInput) -> list[str]: + def top_products(self, example: ExampleInput) -> list[str]: # pragma: no cover return [] schema = strawberry.federation.Schema(query=Query, enable_federation_2=True) @@ -350,7 +352,7 @@ class ProductFed: @strawberry.type class Query: @strawberry.field - def top_products(self, first: int) -> list[ProductFed]: + def top_products(self, first: int) -> list[ProductFed]: # pragma: no cover return [] with warnings.catch_warnings(record=True) as w: diff --git a/tests/fields/test_arguments.py b/tests/fields/test_arguments.py index 0c1b6ec09d..5e7959b789 100644 --- a/tests/fields/test_arguments.py +++ b/tests/fields/test_arguments.py @@ -15,7 +15,9 @@ def test_basic_arguments(): @strawberry.type class Query: @strawberry.field - def name(self, argument: str, optional_argument: Optional[str]) -> str: + def name( + self, argument: str, optional_argument: Optional[str] + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -42,7 +44,9 @@ class Input: @strawberry.type class Query: @strawberry.field - def name(self, input: Input, optional_input: Optional[Input]) -> str: + def name( + self, input: Input, optional_input: Optional[Input] + ) -> str: # pragma: no cover return input.name definition = Query.__strawberry_definition__ @@ -69,7 +73,7 @@ class Input: @strawberry.type class Query: @strawberry.field - def names(self, inputs: list[Input]) -> list[str]: + def names(self, inputs: list[Input]) -> list[str]: # pragma: no cover return [input.name for input in inputs] definition = Query.__strawberry_definition__ @@ -92,7 +96,7 @@ class Input: @strawberry.type class Query: @strawberry.field - def names(self, inputs: list[Optional[Input]]) -> list[str]: + def names(self, inputs: list[Optional[Input]]) -> list[str]: # pragma: no cover return [input_.name for input_ in inputs if input_ is not None] definition = Query.__strawberry_definition__ @@ -109,7 +113,7 @@ def names(self, inputs: list[Optional[Input]]) -> list[str]: def test_basic_arguments_on_resolver(): - def name_resolver( + def name_resolver( # pragma: no cover id: strawberry.ID, argument: str, optional_argument: Optional[str] ) -> str: return "Name" @@ -138,7 +142,7 @@ class Query: def test_arguments_when_extending_a_type(): def name_resolver( id: strawberry.ID, argument: str, optional_argument: Optional[str] - ) -> str: + ) -> str: # pragma: no cover return "Name" @strawberry.type @@ -169,10 +173,10 @@ class Query(NameQuery): def test_arguments_when_extending_multiple_types(): - def name_resolver(id: strawberry.ID) -> str: + def name_resolver(id: strawberry.ID) -> str: # pragma: no cover return "Name" - def name_2_resolver(id: strawberry.ID) -> str: + def name_2_resolver(id: strawberry.ID) -> str: # pragma: no cover return "Name 2" @strawberry.type @@ -210,7 +214,7 @@ def test_argument_with_default_value_none(): @strawberry.type class Query: @strawberry.field - def name(self, argument: Optional[str] = None) -> str: + def name(self, argument: Optional[str] = None) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -231,7 +235,7 @@ def test_argument_with_default_value_undefined(): @strawberry.type class Query: @strawberry.field - def name(self, argument: Optional[str]) -> str: + def name(self, argument: Optional[str]) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -257,7 +261,7 @@ def name( # type: ignore str, strawberry.argument(description="This is a description"), ], - ) -> str: + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -281,7 +285,7 @@ def name( # type: ignore Optional[str], strawberry.argument(description="This is a description"), ], - ) -> str: + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -307,7 +311,7 @@ def name( str, strawberry.argument(description="This is a description"), ] = "Patrick", - ) -> str: + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -333,7 +337,7 @@ def name( str, strawberry.argument(name="argument"), ] = "Patrick", - ) -> str: + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -362,7 +366,7 @@ def name( strawberry.argument(description="This is a description"), strawberry.argument(description="Another description"), ], - ) -> str: + ) -> str: # pragma: no cover return "Name" assert str(error.value) == ( @@ -376,7 +380,9 @@ def test_annotated_with_other_information(): @strawberry.type class Query: @strawberry.field - def name(self, argument: Annotated[str, "Some other info"]) -> str: + def name( + self, argument: Annotated[str, "Some other info"] + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -403,7 +409,7 @@ def name( str, strawberry.argument(description="This is a description"), ], - ) -> str: + ) -> str: # pragma: no cover return "Name" definition = Query.__strawberry_definition__ @@ -465,7 +471,7 @@ def test_resolver_with_invalid_field_argument_type(): class Adjective: text: str - def add_adjective_resolver(adjective: Adjective) -> bool: + def add_adjective_resolver(adjective: Adjective) -> bool: # pragma: no cover return True @strawberry.type diff --git a/tests/litestar/schema.py-E b/tests/litestar/schema.py-E deleted file mode 100644 index 9c6a2a7cc2..0000000000 --- a/tests/litestar/schema.py-E +++ /dev/null @@ -1,157 +0,0 @@ -import asyncio -import typing -from enum import Enum -from typing import Any, Optional - -from graphql import GraphQLError - -import strawberry -from strawberry.file_uploads import Upload -from strawberry.permission import BasePermission -from strawberry.subscriptions.protocols.graphql_transport_ws.types import PingMessage - - -class AlwaysFailPermission(BasePermission): - message = "You are not authorized" - - def has_permission( - self, source: Any, info: strawberry.Info, **kwargs: typing.Any - ) -> bool: - return False - - -@strawberry.enum -class Flavor(Enum): - VANILLA = "vanilla" - STRAWBERRY = "strawberry" - CHOCOLATE = "chocolate" - - -@strawberry.input -class FolderInput: - files: typing.List[Upload] - - -@strawberry.type -class DebugInfo: - num_active_result_handlers: int - is_connection_init_timeout_task_done: typing.Optional[bool] - - -@strawberry.type -class Query: - @strawberry.field - def hello(self, name: typing.Optional[str] = None) -> str: - return f"Hello {name or 'world'}" - - @strawberry.field - async def async_hello(self, name: str, delay: float = 0) -> str: - await asyncio.sleep(delay) - return f"Hello {name or 'world'}" - - @strawberry.field(permission_classes=[AlwaysFailPermission]) - def always_fail(self) -> Optional[str]: - return "Hey" - - @strawberry.field - def root_name(root) -> str: - return type(root).__name__ - - @strawberry.field - async def exception(self, message: str) -> str: - raise ValueError(message) - - -@strawberry.type -class Mutation: - @strawberry.mutation - async def hello(self) -> str: - return "strawberry" - - @strawberry.mutation - async def read_text(self, text_file: Upload) -> str: - return (await text_file.read()).decode() - - @strawberry.mutation - async def read_files(self, files: typing.List[Upload]) -> typing.List[str]: - contents = [] - for file in files: - content = (await file.read()).decode() - contents.append(content) - return contents - - @strawberry.mutation - async def read_folder(self, folder: FolderInput) -> typing.list[str]: - contents = [] - for file in folder.files: - content = (await file.read()).decode() - contents.append(content) - return contents - - -@strawberry.type -class Subscription: - @strawberry.subscription - async def echo( - self, message: str, delay: float = 0 - ) -> typing.AsyncGenerator[str, None]: - await asyncio.sleep(delay) - yield message - - @strawberry.subscription - async def request_ping( - self, info: strawberry.Info - ) -> typing.AsyncGenerator[bool, None]: - ws = info.context["ws"] - await ws.send_json(PingMessage().as_dict()) - yield True - - @strawberry.subscription - async def infinity(self, message: str) -> typing.AsyncGenerator[str, None]: - while True: - yield message - await asyncio.sleep(1) - - @strawberry.subscription - async def context(self, info: strawberry.Info) -> typing.AsyncGenerator[str, None]: - yield info.context["custom_value"] - - @strawberry.subscription - async def error(self, message: str) -> typing.AsyncGenerator[str, None]: - yield GraphQLError(message) # type: ignore - - @strawberry.subscription - async def exception(self, message: str) -> typing.AsyncGenerator[str, None]: - raise ValueError(message) - - # Without this yield, the method is not recognised as an async generator - yield "Hi" - - @strawberry.subscription - async def flavors(self) -> typing.AsyncGenerator[Flavor, None]: - yield Flavor.VANILLA - yield Flavor.STRAWBERRY - yield Flavor.CHOCOLATE - - @strawberry.subscription - async def debug( - self, info: strawberry.Info - ) -> typing.AsyncGenerator[DebugInfo, None]: - active_result_handlers = [ - task for task in info.context["get_tasks"]() if not task.done() - ] - - connection_init_timeout_task = info.context["connectionInitTimeoutTask"] - is_connection_init_timeout_task_done = ( - connection_init_timeout_task.done() - if connection_init_timeout_task - else None - ) - - yield DebugInfo( - num_active_result_handlers=len(active_result_handlers), - is_connection_init_timeout_task_done=is_connection_init_timeout_task_done, - ) - - -schema = strawberry.Schema(Query, mutation=Mutation, subscription=Subscription) diff --git a/tests/relay/test_exceptions.py b/tests/relay/test_exceptions.py index d91a39a7a6..345ae401bb 100644 --- a/tests/relay/test_exceptions.py +++ b/tests/relay/test_exceptions.py @@ -73,7 +73,7 @@ class Fruit(relay.Node): @strawberry.type class Query: @relay.connection(relay.ListConnection[Fruit]) - def fruits(self) -> list[Fruit]: ... + def fruits(self) -> list[Fruit]: ... # pragma: no cover strawberry.Schema(query=Query) @@ -91,7 +91,7 @@ class Fruit(relay.Node): @strawberry.type class Query: @relay.connection(relay.ListConnection[Fruit]) - def fruits(self) -> list[Fruit]: ... + def fruits(self) -> list[Fruit]: ... # pragma: no cover strawberry.Schema(query=Query) @@ -130,7 +130,7 @@ class Fruit(relay.Node): @strawberry.type class Query: @relay.connection(list[Fruit]) # type: ignore - def custom_resolver(self) -> list[Fruit]: ... + def custom_resolver(self) -> list[Fruit]: ... # pragma: no cover strawberry.Schema(query=Query) @@ -150,6 +150,6 @@ class Fruit(relay.Node): @strawberry.type class Query: @relay.connection(relay.Connection[Fruit]) # type: ignore - def custom_resolver(self): ... + def custom_resolver(self): ... # pragma: no cover strawberry.Schema(query=Query) diff --git a/tests/schema/test_extensions.py b/tests/schema/test_extensions.py index 286cfca0a7..542f8c1ef9 100644 --- a/tests/schema/test_extensions.py +++ b/tests/schema/test_extensions.py @@ -52,7 +52,7 @@ class Query: def test_directive(): @strawberry.directive(locations=[DirectiveLocation.FIELD]) - def uppercase(value: DirectiveValue[str], foo: str): + def uppercase(value: DirectiveValue[str], foo: str): # pragma: no cover return value.upper() @strawberry.type() diff --git a/tests/schema/test_resolvers.py-E b/tests/schema/test_resolvers.py-E deleted file mode 100644 index 1be5cdb40c..0000000000 --- a/tests/schema/test_resolvers.py-E +++ /dev/null @@ -1,645 +0,0 @@ -# type: ignore -import typing -from contextlib import nullcontext -from typing import Any, Generic, NamedTuple, Optional, TypeVar, Union - -import pytest - -import strawberry -from strawberry.exceptions import ConflictingArgumentsError -from strawberry.parent import Parent -from strawberry.types.info import Info - - -def test_resolver(): - @strawberry.type - class Query: - @strawberry.field - def hello(self) -> str: - return "I'm a resolver" - - schema = strawberry.Schema(query=Query) - - query = "{ hello }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data["hello"] == "I'm a resolver" - - -@pytest.mark.asyncio -async def test_resolver_function(): - def function_resolver(root) -> str: - return "I'm a function resolver" - - async def async_resolver(root) -> str: - return "I'm an async resolver" - - def resolve_name(root) -> str: - return root.name - - def resolve_say_hello(root, name: str) -> str: - return f"Hello {name}" - - @strawberry.type - class Query: - hello: str = strawberry.field(resolver=function_resolver) - hello_async: str = strawberry.field(resolver=async_resolver) - get_name: str = strawberry.field(resolver=resolve_name) - say_hello: str = strawberry.field(resolver=resolve_say_hello) - - name = "Patrick" - - schema = strawberry.Schema(query=Query) - - query = """{ - hello - helloAsync - getName - sayHello(name: "Marco") - }""" - - result = await schema.execute(query, root_value=Query()) - - assert not result.errors - assert result.data["hello"] == "I'm a function resolver" - assert result.data["helloAsync"] == "I'm an async resolver" - assert result.data["getName"] == "Patrick" - assert result.data["sayHello"] == "Hello Marco" - - -def test_resolvers_on_types(): - def function_resolver(root) -> str: - return "I'm a function resolver" - - def function_resolver_with_params(root, x: str) -> str: - return f"I'm {x}" - - @strawberry.type - class Example: - hello: str = strawberry.field(resolver=function_resolver) - hello_with_params: str = strawberry.field( - resolver=function_resolver_with_params - ) - - @strawberry.type - class Query: - @strawberry.field - def example(self) -> Example: - return Example() - - schema = strawberry.Schema(query=Query) - - query = """{ - example { - hello - helloWithParams(x: "abc") - } - }""" - - result = schema.execute_sync(query, root_value=Query()) - - assert not result.errors - assert result.data["example"]["hello"] == "I'm a function resolver" - assert result.data["example"]["helloWithParams"] == "I'm abc" - - -def test_optional_info_and_root_params_function_resolver(): - def function_resolver() -> str: - return "I'm a function resolver" - - def function_resolver_with_root(root) -> str: - return root._example - - def function_resolver_with_params(x: str) -> str: - return f"I'm {x}" - - @strawberry.type - class Query: - hello: str = strawberry.field(resolver=function_resolver) - hello_with_root: str = strawberry.field(resolver=function_resolver_with_root) - hello_with_params: str = strawberry.field( - resolver=function_resolver_with_params - ) - - def __post_init__(self): - self._example = "Example" - - schema = strawberry.Schema(query=Query) - - query = """{ - hello - helloWithRoot - helloWithParams(x: "abc") - }""" - - result = schema.execute_sync(query, root_value=Query()) - - assert not result.errors - assert result.data["hello"] == "I'm a function resolver" - assert result.data["helloWithParams"] == "I'm abc" - assert result.data["helloWithRoot"] == "Example" - - -def test_optional_info_and_root_params(): - @strawberry.type - class Query: - @strawberry.field - def hello(self) -> str: - return "I'm a function resolver" - - @strawberry.field - def hello_with_params(self, x: str) -> str: - return f"I'm {x}" - - @strawberry.field - def uses_self(self) -> str: - return f"I'm {self._example}" - - def __post_init__(self): - self._example = "self" - - schema = strawberry.Schema(query=Query) - - query = """{ - hello - helloWithParams(x: "abc") - usesSelf - }""" - - result = schema.execute_sync(query, root_value=Query()) - - assert not result.errors - assert result.data["hello"] == "I'm a function resolver" - assert result.data["helloWithParams"] == "I'm abc" - assert result.data["usesSelf"] == "I'm self" - - -def test_only_info_function_resolvers(): - def function_resolver(info: strawberry.Info) -> str: - return f"I'm a function resolver for {info.field_name}" - - def function_resolver_with_params(info: strawberry.Info, x: str) -> str: - return f"I'm {x} for {info.field_name}" - - @strawberry.type - class Query: - hello: str = strawberry.field(resolver=function_resolver) - hello_with_params: str = strawberry.field( - resolver=function_resolver_with_params - ) - - schema = strawberry.Schema(query=Query) - - query = """{ - hello - helloWithParams(x: "abc") - }""" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data["hello"] == "I'm a function resolver for hello" - # TODO: in future, should we map names of info.field_name to the matching - # dataclass field name? - assert result.data["helloWithParams"] == "I'm abc for helloWithParams" - - -def test_classmethod_resolvers(): - global User - - @strawberry.type - class User: - name: str - age: int - - @classmethod - def get_users(cls) -> "list[User]": - return [cls(name="Bob", age=10), cls(name="Nancy", age=30)] - - @strawberry.type - class Query: - users: typing.list[User] = strawberry.field(resolver=User.get_users) - - schema = strawberry.Schema(query=Query) - - query = "{ users { name } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"users": [{"name": "Bob"}, {"name": "Nancy"}]} - - del User - - -def test_staticmethod_resolvers(): - class Alphabet: - @staticmethod - def get_letters() -> list[str]: - return ["a", "b", "c"] - - @strawberry.type - class Query: - letters: list[str] = strawberry.field(resolver=Alphabet.get_letters) - - schema = strawberry.Schema(query=Query) - - query = "{ letters }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"letters": ["a", "b", "c"]} - - -def test_lambda_resolvers(): - @strawberry.type - class Query: - letter: str = strawberry.field(resolver=lambda: "λ") - - schema = strawberry.Schema(query=Query) - - query = "{ letter }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"letter": "λ"} - - -def test_bounded_instance_method_resolvers(): - class CoolClass: - def method(self): - _ = self - return "something" - - instance = CoolClass() - - @strawberry.type - class Query: - blah: str = strawberry.field(resolver=instance.method) - - schema = strawberry.Schema(query=Query) - - query = "{ blah }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"blah": "something"} - - -def test_extending_type(): - def name_resolver(id: strawberry.ID) -> str: - return "Name" - - def name_2_resolver(id: strawberry.ID) -> str: - return "Name 2" - - @strawberry.type - class NameQuery: - name: str = strawberry.field(permission_classes=[], resolver=name_resolver) - - @strawberry.type - class ExampleQuery: - name_2: str = strawberry.field(permission_classes=[], resolver=name_2_resolver) - - @strawberry.type - class RootQuery(NameQuery, ExampleQuery): - pass - - schema = strawberry.Schema(query=RootQuery) - - query = '{ name(id: "abc"), name2(id: "abc") }' - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"name": "Name", "name2": "Name 2"} - - -@pytest.mark.asyncio -async def test_async_list_resolver(): - @strawberry.type - class Query: - @strawberry.field - async def best_flavours(self) -> list[str]: - return ["strawberry", "pistachio"] - - schema = strawberry.Schema(query=Query) - - query = "{ bestFlavours }" - - result = await schema.execute(query, root_value=Query()) - - assert not result.errors - assert result.data["bestFlavours"] == ["strawberry", "pistachio"] - - -def test_can_use_source_as_argument_name(): - @strawberry.type - class Query: - @strawberry.field - def hello(self, source: str) -> str: - return f"I'm a resolver for {source}" - - schema = strawberry.Schema(query=Query) - - query = '{ hello(source: "🍓") }' - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data["hello"] == "I'm a resolver for 🍓" - - -def test_generic_resolver_factory(): - @strawberry.type - class AType: - some: int - - T = TypeVar("T") - - def resolver_factory(strawberry_type: type[T]): - def resolver() -> T: - return strawberry_type(some=1) - - return resolver - - @strawberry.type - class Query: - a_type: AType = strawberry.field(resolver_factory(AType)) - - strawberry.Schema(query=Query) - - schema = strawberry.Schema(query=Query) - - query = "{ aType { some } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"aType": {"some": 1}} - - -def test_generic_resolver_optional(): - @strawberry.type - class AType: - some: int - - T = TypeVar("T") - - def resolver() -> Optional[T]: - return AType(some=1) - - @strawberry.type - class Query: - a_type: Optional[AType] = strawberry.field(resolver) - - strawberry.Schema(query=Query) - - schema = strawberry.Schema(query=Query) - - query = "{ aType { some } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"aType": {"some": 1}} - - -def test_generic_resolver_container(): - T = TypeVar("T") - - @strawberry.type - class Container(Generic[T]): - item: T - - @strawberry.type - class AType: - some: int - - def resolver() -> Container[T]: - return Container(item=AType(some=1)) - - @strawberry.type - class Query: - a_type_in_container: Container[AType] = strawberry.field(resolver) - - strawberry.Schema(query=Query) - - schema = strawberry.Schema(query=Query) - - query = "{ aTypeInContainer { item { some } } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"aTypeInContainer": {"item": {"some": 1}}} - - -def test_generic_resolver_union(): - T = TypeVar("T") - - @strawberry.type - class AType: - some: int - - @strawberry.type - class OtherType: - other: int - - def resolver() -> Union[T, OtherType]: - return AType(some=1) - - @strawberry.type - class Query: - union_type: Union[AType, OtherType] = strawberry.field(resolver) - - strawberry.Schema(query=Query) - - schema = strawberry.Schema(query=Query) - - query = "{ unionType { ... on AType { some } } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"unionType": {"some": 1}} - - -def test_generic_resolver_list(): - T = TypeVar("T") - - @strawberry.type - class AType: - some: int - - def resolver() -> list[T]: - return [AType(some=1)] - - @strawberry.type - class Query: - list_type: list[AType] = strawberry.field(resolver) - - strawberry.Schema(query=Query) - - schema = strawberry.Schema(query=Query) - - query = "{ listType { some } }" - - result = schema.execute_sync(query) - - assert not result.errors - assert result.data == {"listType": [{"some": 1}]} - - -def name_based_info(info, icon: str) -> str: - return f"I'm a resolver for {icon} {info.field_name}" - - -def type_based_info(info: strawberry.Info, icon: str) -> str: - return f"I'm a resolver for {icon} {info.field_name}" - - -def generic_type_based_info(icon: str, info: strawberry.Info) -> str: - return f"I'm a resolver for {icon} {info.field_name}" - - -def arbitrarily_named_info(icon: str, info_argument: Info) -> str: - return f"I'm a resolver for {icon} {info_argument.field_name}" - - -@pytest.mark.parametrize( - ("resolver", "deprecation"), - ( - pytest.param( - name_based_info, - pytest.deprecated_call(match="Argument name-based matching of"), - ), - pytest.param(type_based_info, nullcontext()), - pytest.param(generic_type_based_info, nullcontext()), - pytest.param(arbitrarily_named_info, nullcontext()), - ), -) -def test_info_argument(resolver, deprecation): - with deprecation: - - @strawberry.type - class ResolverGreeting: - hello: str = strawberry.field(resolver=resolver) - - schema = strawberry.Schema(query=ResolverGreeting) - result = schema.execute_sync('{ hello(icon: "🍓") }') - - assert not result.errors - assert result.data["hello"] == "I'm a resolver for 🍓 hello" - - -def test_name_based_info_is_deprecated(): - with pytest.deprecated_call(match=r"Argument name-based matching of 'info'"): - - @strawberry.type - class Query: - @strawberry.field - def foo(info: Any) -> str: ... - - strawberry.Schema(query=Query) - - -class UserLiteral(NamedTuple): - id: str - - -def parent_no_self(parent: Parent[UserLiteral]) -> str: - return f"User {parent.id}" - - -class Foo: - @staticmethod - def static_method_parent(asdf: Parent[UserLiteral]) -> str: - return f"User {asdf.id}" - - -@pytest.mark.parametrize( - "resolver", - ( - pytest.param(parent_no_self), - pytest.param(Foo.static_method_parent), - ), -) -def test_parent_argument(resolver): - @strawberry.type - class User: - id: str - name: str = strawberry.field(resolver=resolver) - - @strawberry.type - class Query: - @strawberry.field - def user(self, user_id: str) -> User: - return UserLiteral(user_id) - - schema = strawberry.Schema(query=Query) - result = schema.execute_sync('{ user(userId: "🍓") { name } }') - assert not result.errors - assert result.data["user"]["name"] == "User 🍓" - - -def parent_and_self(self, parent: Parent[UserLiteral]) -> str: - raise AssertionError("Unreachable code.") - - -def parent_self_and_root(self, root, parent: Parent[UserLiteral]) -> str: - raise AssertionError("Unreachable code.") - - -def self_and_root(self, root) -> str: - raise AssertionError("Unreachable code.") - - -def multiple_parents(user: Parent[Any], user2: Parent[Any]) -> str: - raise AssertionError("Unreachable code.") - - -def multiple_infos(root, info1: Info, info2: Info) -> str: - raise AssertionError("Unreachable code.") - - -@pytest.mark.parametrize( - "resolver", - ( - pytest.param(parent_self_and_root), - pytest.param(multiple_parents), - pytest.param(multiple_infos), - pytest.param( - parent_and_self, - marks=pytest.mark.xfail( - strict=True, - reason="`self` should not raise ConflictingArgumentsError", - ), - ), - pytest.param( - self_and_root, - marks=pytest.mark.xfail( - strict=True, - reason="`self` should not raise ConflictingArgumentsError", - ), - ), - ), -) -@pytest.mark.raises_strawberry_exception( - ConflictingArgumentsError, - match=( - "Arguments .* define conflicting resources. " - "Only one of these arguments may be defined per resolver." - ), -) -def test_multiple_conflicting_reserved_arguments(resolver): - @strawberry.type - class Query: - name: str = strawberry.field(resolver=resolver) - - strawberry.Schema(query=Query) diff --git a/tests/test_forward_references.py b/tests/test_forward_references.py index 46684b4ee5..0e1831795c 100644 --- a/tests/test_forward_references.py +++ b/tests/test_forward_references.py @@ -53,7 +53,7 @@ def test_lazy_forward_reference(): @strawberry.type class Query: @strawberry.field - async def a(self) -> A: + async def a(self) -> A: # pragma: no cover return A(id=strawberry.ID("1")) expected_representation = """ @@ -114,7 +114,7 @@ def test_with_resolver(): class User: name: str - def get_users() -> list[User]: + def get_users() -> list[User]: # pragma: no cover return [] @strawberry.type @@ -140,7 +140,7 @@ def test_union_or_notation(): class User: name: str - def get_users() -> list[User] | None: + def get_users() -> list[User] | None: # pragma: no cover return [] @strawberry.type @@ -167,7 +167,7 @@ def test_union_or_notation_generic_type_alias(): class User: name: str - def get_users() -> list[User] | None: + def get_users() -> list[User] | None: # pragma: no cover return [] @strawberry.type @@ -194,7 +194,7 @@ def test_annotated(): class User: name: str - def get_users() -> list[User]: + def get_users() -> list[User]: # pragma: no cover return [] @strawberry.type @@ -220,7 +220,7 @@ def test_annotated_or_notation(): class User: name: str - def get_users() -> list[User] | None: + def get_users() -> list[User] | None: # pragma: no cover return [] @strawberry.type @@ -249,7 +249,7 @@ def test_annotated_or_notation_generic_type_alias(): class User: name: str - def get_users() -> list[User]: + def get_users() -> list[User]: # pragma: no cover return [] @strawberry.type diff --git a/tests/typecheckers/test_relay.py b/tests/typecheckers/test_relay.py index 9a11d9412b..e958c95e99 100644 --- a/tests/typecheckers/test_relay.py +++ b/tests/typecheckers/test_relay.py @@ -15,7 +15,6 @@ Generator, Iterable, Iterator, - List, Optional, Union, ) @@ -161,198 +160,196 @@ def test(): Result( type="information", message='Type of "Query.node" is "Node"', - line=131, + line=130, column=13, ), Result( type="information", message='Type of "Query.nodes" is "list[Node]"', - line=132, + line=131, column=13, ), Result( type="information", message='Type of "Query.node_optional" is "Node | None"', - line=133, + line=132, column=13, ), Result( type="information", message='Type of "Query.nodes_optional" is "list[Node | None]"', - line=134, + line=133, column=13, ), Result( type="information", message='Type of "Query.fruits" is "Connection[Fruit]"', - line=135, + line=134, column=13, ), Result( type="information", message='Type of "Query.fruits_conn" is "Connection[Fruit]"', - line=136, + line=135, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_pagination" is "FruitCustomPaginationConnection"', - line=137, + line=136, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver" is "Any"', - line=138, + line=137, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_iterator" is "Any"', - line=139, + line=138, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_iterable" is "Any"', - line=140, + line=139, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_generator" is "Any"', - line=141, + line=140, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_async_iterator" is "Any"', - line=142, + line=141, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_async_iterable" is "Any"', - line=143, + line=142, column=13, ), Result( type="information", message='Type of "Query.fruits_custom_resolver_async_generator" is "Any"', - line=144, + line=143, column=13, ), ] ) assert results.mypy == snapshot( [ - Result(type="error", message="Missing return statement", line=34, column=5), - Result(type="error", message="Missing return statement", line=57, column=1), + Result(type="error", message="Missing return statement", line=33, column=5), + Result(type="error", message="Missing return statement", line=56, column=1), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver" untyped', - line=75, + line=74, column=6, ), - Result(type="error", message="Missing return statement", line=76, column=5), + Result(type="error", message="Missing return statement", line=75, column=5), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_iterator" untyped', - line=83, + line=82, column=6, ), - Result(type="error", message="Missing return statement", line=84, column=5), + Result(type="error", message="Missing return statement", line=83, column=5), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_iterable" untyped', - line=91, + line=90, column=6, ), - Result(type="error", message="Missing return statement", line=92, column=5), + Result(type="error", message="Missing return statement", line=91, column=5), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_generator" untyped', - line=99, + line=98, column=6, ), - Result( - type="error", message="Missing return statement", line=100, column=5 - ), + Result(type="error", message="Missing return statement", line=99, column=5), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_async_iterator" untyped', - line=107, + line=106, column=6, ), Result( - type="error", message="Missing return statement", line=108, column=5 + type="error", message="Missing return statement", line=107, column=5 ), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_async_iterable" untyped', - line=115, + line=114, column=6, ), Result( - type="error", message="Missing return statement", line=116, column=5 + type="error", message="Missing return statement", line=115, column=5 ), Result( type="error", message='Untyped decorator makes function "fruits_custom_resolver_async_generator" untyped', - line=123, + line=122, column=6, ), Result( - type="error", message="Missing return statement", line=124, column=5 + type="error", message="Missing return statement", line=123, column=5 ), Result( type="note", message='Revealed type is "strawberry.relay.types.Node"', - line=131, + line=130, column=13, ), Result( type="note", message='Revealed type is "builtins.list[strawberry.relay.types.Node]"', - line=132, + line=131, column=13, ), Result( type="note", message='Revealed type is "Union[strawberry.relay.types.Node, None]"', - line=133, + line=132, column=13, ), Result( type="note", message='Revealed type is "builtins.list[Union[strawberry.relay.types.Node, None]]"', - line=134, + line=133, column=13, ), Result( type="note", message='Revealed type is "strawberry.relay.types.Connection[mypy_test.Fruit]"', - line=135, + line=134, column=13, ), Result( type="note", message='Revealed type is "strawberry.relay.types.Connection[mypy_test.Fruit]"', - line=136, + line=135, column=13, ), Result( type="note", message='Revealed type is "mypy_test.FruitCustomPaginationConnection"', - line=137, + line=136, column=13, ), + Result(type="note", message='Revealed type is "Any"', line=137, column=13), Result(type="note", message='Revealed type is "Any"', line=138, column=13), Result(type="note", message='Revealed type is "Any"', line=139, column=13), Result(type="note", message='Revealed type is "Any"', line=140, column=13), Result(type="note", message='Revealed type is "Any"', line=141, column=13), Result(type="note", message='Revealed type is "Any"', line=142, column=13), Result(type="note", message='Revealed type is "Any"', line=143, column=13), - Result(type="note", message='Revealed type is "Any"', line=144, column=13), ] ) diff --git a/tests/types/cross_module_resolvers/x_mod.py b/tests/types/cross_module_resolvers/x_mod.py index 918a4f4a4d..80be36ee10 100644 --- a/tests/types/cross_module_resolvers/x_mod.py +++ b/tests/types/cross_module_resolvers/x_mod.py @@ -1,2 +1,2 @@ -def typeless_resolver() -> list: +def typeless_resolver() -> list: # pragma: no cover return []