diff --git a/graphql/execution/tests/test_executor.py b/graphql/execution/tests/test_executor.py index f20f5687..69b64e45 100644 --- a/graphql/execution/tests/test_executor.py +++ b/graphql/execution/tests/test_executor.py @@ -116,7 +116,7 @@ def deeper(self): "f": GraphQLField(GraphQLString), "pic": GraphQLField( args={"size": GraphQLArgument(GraphQLInt)}, - type=GraphQLString, + type_=GraphQLString, resolver=lambda obj, info, size: obj.pic(size), ), "deep": GraphQLField(DeepDataType), diff --git a/graphql/type/definition.py b/graphql/type/definition.py index 3f8d2ba0..8e5d12f4 100644 --- a/graphql/type/definition.py +++ b/graphql/type/definition.py @@ -6,6 +6,8 @@ from collections import Hashable, Mapping import copy +from typing import Union + from ..language import ast from ..pyutils.cached_property import cached_property from ..pyutils.ordereddict import OrderedDict @@ -15,13 +17,13 @@ # Necessary for static type checking if False: # flake8: noqa - from typing import List, Dict, Any, Callable, Optional, Union, Type + from typing import List, Dict, Any, Callable, Optional, Type -def is_type(type): +def is_type(type_): # type: (Any) -> bool return isinstance( - type, + type_, ( GraphQLScalarType, GraphQLObjectType, @@ -35,55 +37,23 @@ def is_type(type): ) -def is_input_type(type): +def is_input_type(type_): # type: (Any) -> bool - named_type = get_named_type(type) + named_type = get_named_type(type_) return isinstance( named_type, (GraphQLScalarType, GraphQLEnumType, GraphQLInputObjectType) ) -def is_output_type(type): - # type: (Any) -> bool - named_type = get_named_type(type) - return isinstance( - named_type, - ( - GraphQLScalarType, - GraphQLObjectType, - GraphQLInterfaceType, - GraphQLUnionType, - GraphQLEnumType, - ), - ) - - -def is_leaf_type(type): - # type: (Any) -> bool - return isinstance(type, (GraphQLScalarType, GraphQLEnumType)) +def get_nullable_type(type_): + if isinstance(type_, GraphQLNonNull): + return type_.of_type + return type_ -def is_composite_type(type): - # type: (Any) -> bool - named_type = get_named_type(type) - return isinstance( - named_type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType) - ) - - -def is_abstract_type(type): - return isinstance(type, (GraphQLInterfaceType, GraphQLUnionType)) - - -def get_nullable_type(type): - if isinstance(type, GraphQLNonNull): - return type.of_type - return type - - -def get_named_type(type): +def get_named_type(type_): # type: (Optional[GraphQLType]) -> Optional[GraphQLType] - unmodified_type = type + unmodified_type = type_ while isinstance(unmodified_type, (GraphQLList, GraphQLNonNull)): unmodified_type = unmodified_type.of_type @@ -111,7 +81,7 @@ def is_same_type(self, other): def none_func(x): - None + return None class GraphQLScalarType(GraphQLNamedType): @@ -144,6 +114,7 @@ def __init__( # type: (...) -> None assert name, "Type must be named." assert_valid_name(name) + super(GraphQLScalarType, self).__init__(name) self.name = name self.description = description @@ -207,6 +178,7 @@ def __init__( # type: (...) -> None assert name, "Type must be named." assert_valid_name(name) + super(GraphQLObjectType, self).__init__(name) self.name = name self.description = description @@ -232,7 +204,7 @@ def interfaces(self): def define_field_map( - type, # type: Union[GraphQLInterfaceType, GraphQLObjectType] + type_, # type: Union[GraphQLInterfaceType, GraphQLObjectType] field_map, # type: Union[Callable, Dict[str, GraphQLField], OrderedDict] ): # type: (...) -> OrderedDict @@ -242,20 +214,20 @@ def define_field_map( assert isinstance(field_map, Mapping) and len(field_map) > 0, ( "{} fields must be a mapping (dict / OrderedDict) with field names as keys or a " "function which returns such a mapping." - ).format(type) + ).format(type_) for field_name, field in field_map.items(): assert_valid_name(field_name) assert isinstance( field, GraphQLField - ), "{}.{} must be an instance of GraphQLField.".format(type, field_name) + ), "{}.{} must be an instance of GraphQLField.".format(type_, field_name) field_args = getattr(field, "args", None) if field_args: assert isinstance( field_args, Mapping ), "{}.{} args must be a mapping (dict / OrderedDict) with argument names as keys.".format( - type, field_name + type_, field_name ) for arg_name, arg in field_args.items(): @@ -265,7 +237,7 @@ def define_field_map( def define_interfaces( - type, # type: GraphQLObjectType + type_, # type: GraphQLObjectType interfaces, # type: Optional[List[GraphQLInterfaceType]] ): # type: (...) -> List[GraphQLInterfaceType] @@ -278,23 +250,23 @@ def define_interfaces( assert isinstance( interfaces, (list, tuple) ), "{} interfaces must be a list/tuple or a function which returns a list/tuple.".format( - type + type_ ) for interface in interfaces: assert isinstance( interface, GraphQLInterfaceType ), "{} may only implement Interface types, it cannot implement: {}.".format( - type, interface + type_, interface ) if not callable(interface.resolve_type): - assert callable(type.is_type_of), ( + assert callable(type_.is_type_of), ( 'Interface Type {} does not provide a "resolve_type" function ' 'and implementing Type {} does not provide a "is_type_of" ' "function. There is no way to resolve this implementing type " "during execution." - ).format(interface, type) + ).format(interface, type_) return interfaces @@ -304,14 +276,14 @@ class GraphQLField(object): def __init__( self, - type, # type: Any + type_, # type: Any args=None, # type: Optional[Dict[str, GraphQLArgument]] resolver=None, # type: Optional[Callable] deprecation_reason=None, # type: Optional[Any] description=None, # type: Optional[Any] ): # type: (...) -> None - self.type = type + self.type = type_ self.args = args or OrderedDict() self.resolver = resolver self.deprecation_reason = deprecation_reason @@ -341,13 +313,13 @@ class GraphQLArgument(object): def __init__( self, - type, # type: Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType] + type_, # type: Union[GraphQLInputObjectType, GraphQLNonNull, GraphQLList, GraphQLScalarType] default_value=None, # type: Optional[Any] description=None, # type: Optional[Any] out_name=None, # type: Optional[str] ): # type: (...) -> None - self.type = type + self.type = type_ self.default_value = default_value self.description = description self.out_name = out_name @@ -368,8 +340,9 @@ def __hash__(self): class GraphQLInterfaceType(GraphQLNamedType): """Interface Type Definition - When a field can return one of a heterogeneous set of types, a Interface type is used to describe what types are possible, - what fields are in common across all types, as well as a function to determine which type is actually used when the field is resolved. + When a field can return one of a heterogeneous set of types, a Interface type is used to describe what types + are possible, what fields are in common across all types, as well as a function to determine which type + is actually used when the field is resolved. Example: @@ -390,6 +363,7 @@ def __init__( # type: (...) -> None assert name, "Type must be named." assert_valid_name(name) + super(GraphQLInterfaceType, self).__init__(name) self.name = name self.description = description @@ -437,6 +411,7 @@ def __init__( # type: (...) -> None assert name, "Type must be named." assert_valid_name(name) + super(GraphQLUnionType, self).__init__(name) self.name = name self.description = description @@ -469,20 +444,20 @@ def define_types( ), "Must provide types for Union {}.".format(union_type.name) has_resolve_type_fn = callable(union_type.resolve_type) - for type in types: + for type_ in types: assert isinstance( - type, GraphQLObjectType + type_, GraphQLObjectType ), "{} may only contain Object types, it cannot contain: {}.".format( - union_type, type + union_type, type_ ) if not has_resolve_type_fn: - assert callable(type.is_type_of), ( + assert callable(type_.is_type_of), ( 'Union Type {} does not provide a "resolve_type" function ' 'and possible Type {} does not provide a "is_type_of" ' "function. There is no way to resolve this possible type " "during execution." - ).format(union_type, type) + ).format(union_type, type_) return types @@ -510,6 +485,7 @@ class GraphQLEnumType(GraphQLNamedType): def __init__(self, name, values, description=None): assert name, "Type must provide name." assert_valid_name(name) + super(GraphQLEnumType, self).__init__(name) self.name = name self.description = description @@ -648,6 +624,7 @@ def __init__( assert name, "Type must be named." self.name = name self.description = description + super(GraphQLInputObjectType, self).__init__(name) if container_type is None: container_type = OrderedDict # type: ignore assert callable(container_type), "container_type must be callable" @@ -688,13 +665,13 @@ class GraphQLInputObjectField(object): def __init__( self, - type, # type: Union[GraphQLInputObjectType, GraphQLScalarType] + type_, # type: Union[GraphQLInputObjectType, GraphQLScalarType] default_value=None, # type: Optional[Any] description=None, # type: Optional[Any] out_name=None, # type: str ): # type: (...) -> None - self.type = type + self.type = type_ # type: Union[GraphQLInputObjectType, GraphQLScalarType] self.default_value = default_value self.description = description self.out_name = out_name @@ -729,12 +706,12 @@ def get_fields(self): __slots__ = ("of_type",) - def __init__(self, type): + def __init__(self, type_): # type: (Any) -> None assert is_type( - type - ), "Can only create List of a GraphQLType but got: {}.".format(type) - self.of_type = type + type_ + ), "Can only create List of a GraphQLType but got: {}.".format(type_) + self.of_type = type_ def __str__(self): # type: () -> str @@ -746,12 +723,40 @@ def is_same_type(self, other): ) +# These types can all accept null as a value. +graphql_nullable_types = ( + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, +) + +GraphQLNullableType = Union[ + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLInputObjectType, + GraphQLList, +] + + +def is_nullable_type(type_): + # type: (Any) -> bool + return isinstance(type_, graphql_nullable_types) + + class GraphQLNonNull(GraphQLType): """Non-Null Modifier - A non-null is a kind of type marker, a wrapping type which points to another type. Non-null types enforce that their values are never null - and can ensure an error is raised if this ever occurs during a request. It is useful for fields which you can make a strong guarantee on - non-nullability, for example usually the id field of a database row will never be null. + A non-null is a kind of type marker, a wrapping type which points to another type. Non-null types enforce + that their values are never null and can ensure an error is raised if this ever occurs during a request. + It is useful for fields which you can make a strong guarantee on non-nullability, + for example usually the id field of a database row will never be null. Example: @@ -768,13 +773,13 @@ class RowType(GraphQLObjectType): def __init__( self, - type, # type: Union[GraphQLList, GraphQLObjectType, GraphQLScalarType, GraphQLInputObjectType, GraphQLInterfaceType] + type_, # type: GraphQLNullableType ): # type: (...) -> None - assert is_type(type) and not isinstance( - type, GraphQLNonNull - ), "Can only create NonNull of a Nullable GraphQLType but got: {}.".format(type) - self.of_type = type + assert is_type(type_) and not isinstance( + type_, GraphQLNonNull + ), "Can only create NonNull of a Nullable GraphQLType but got: {}.".format(type_) + self.of_type = type_ # type: GraphQLNullableType def __str__(self): # type: () -> str @@ -784,3 +789,87 @@ def is_same_type(self, other): return isinstance(other, GraphQLNonNull) and self.of_type.is_same_type( other.of_type ) + + +# These types may be used as output types as the result of fields. +graphql_output_types = ( + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, +) + +GraphQLOutputType = Union[ + GraphQLScalarType, + GraphQLObjectType, + GraphQLInterfaceType, + GraphQLUnionType, + GraphQLEnumType, + GraphQLNullableType +] + + +def is_output_type(type_): + # type: (Any) -> bool + named_type = get_named_type(type_) + return isinstance(named_type, graphql_output_types) + + +def is_union_type(type_): + # type: (Any) -> bool + return isinstance(type_, GraphQLUnionType) + + +def is_interface_type(type_): + # type: (Any) -> bool + return isinstance(type_, GraphQLInterfaceType) + + +def is_list_type(type_): + # type: (Any) -> bool + return isinstance(type_, GraphQLList) + + +def is_non_null_type(type_): + # type: (Any) -> bool + return isinstance(type_, GraphQLNonNull) + + +def is_object_type(type_): + # type: (Any) -> bool + return isinstance(type_, GraphQLObjectType) + + +# These types may describe types which may be leaf values. +graphql_leaf_types = (GraphQLScalarType, GraphQLEnumType) + +GraphQLLeafType = Union[GraphQLScalarType, GraphQLEnumType] + + +def is_leaf_type(type_): + # type: (Any) -> bool + return isinstance(type_, (GraphQLScalarType, GraphQLEnumType)) + + +# These types may describe the parent context of a selection set. +graphql_composite_types = (GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType) + +GraphQLCompositeType = Union[GraphQLObjectType, GraphQLInterfaceType, GraphQLUnionType] + + +def is_composite_type(type_): + # type: (Any) -> bool + named_type = get_named_type(type_) + return isinstance(named_type, graphql_composite_types) + + +# These types may describe abstract types. +graphql_abstract_types = (GraphQLInterfaceType, GraphQLUnionType) + +GraphQLAbstractType = Union[GraphQLInterfaceType, GraphQLUnionType] + + +def is_abstract_type(type_): + # type: (Any) -> bool + return isinstance(type_, graphql_abstract_types) diff --git a/graphql/type/directives.py b/graphql/type/directives.py index 9e398a1b..ea1aa720 100644 --- a/graphql/type/directives.py +++ b/graphql/type/directives.py @@ -71,7 +71,7 @@ def __init__(self, name, description=None, args=None, locations=None): description="Directs the executor to include this field or fragment only when the `if` argument is true.", args={ "if": GraphQLArgument( - type=GraphQLNonNull(GraphQLBoolean), description="Included when true." + type_=GraphQLNonNull(GraphQLBoolean), description="Included when true." ) }, locations=[ @@ -87,7 +87,7 @@ def __init__(self, name, description=None, args=None, locations=None): description="Directs the executor to skip this field or fragment when the `if` argument is true.", args={ "if": GraphQLArgument( - type=GraphQLNonNull(GraphQLBoolean), description="Skipped when true." + type_=GraphQLNonNull(GraphQLBoolean), description="Skipped when true." ) }, locations=[ @@ -106,7 +106,7 @@ def __init__(self, name, description=None, args=None, locations=None): description="Marks an element of a GraphQL schema as no longer supported.", args={ "reason": GraphQLArgument( - type=GraphQLString, + type_=GraphQLString, description=( "Explains why this element was deprecated, usually also including a suggestion for how to" "access supported similar data. Formatted in [Markdown]" diff --git a/graphql/type/introspection.py b/graphql/type/introspection.py index 520011f2..e392b82d 100644 --- a/graphql/type/introspection.py +++ b/graphql/type/introspection.py @@ -56,7 +56,7 @@ def input_fields_to_list(input_fields): "types", GraphQLField( description="A list of all types supported by this server.", - type=GraphQLNonNull( + type_=GraphQLNonNull( GraphQLList(GraphQLNonNull(__Type)) # type: ignore ), resolver=lambda schema, *_: schema.get_type_map().values(), @@ -66,7 +66,7 @@ def input_fields_to_list(input_fields): "queryType", GraphQLField( description="The type that query operations will be rooted at.", - type=GraphQLNonNull(__Type), # type: ignore + type_=GraphQLNonNull(__Type), # type: ignore resolver=lambda schema, *_: schema.get_query_type(), ), ), @@ -75,7 +75,7 @@ def input_fields_to_list(input_fields): GraphQLField( description="If this server supports mutation, the type that " "mutation operations will be rooted at.", - type=__Type, # type: ignore + type_=__Type, # type: ignore resolver=lambda schema, *_: schema.get_mutation_type(), ), ), @@ -84,7 +84,7 @@ def input_fields_to_list(input_fields): GraphQLField( description="If this server support subscription, the type " "that subscription operations will be rooted at.", - type=__Type, # type: ignore + type_=__Type, # type: ignore resolver=lambda schema, *_: schema.get_subscription_type(), ), ), @@ -92,7 +92,7 @@ def input_fields_to_list(input_fields): "directives", GraphQLField( description="A list of all directives supported by this server.", - type=GraphQLNonNull( + type_=GraphQLNonNull( GraphQLList(GraphQLNonNull(__Directive)) # type: ignore ), resolver=lambda schema, *_: schema.get_directives(), @@ -121,7 +121,7 @@ def input_fields_to_list(input_fields): ( "locations", GraphQLField( - type=GraphQLNonNull( + type_=GraphQLNonNull( GraphQLList(GraphQLNonNull(__DirectiveLocation)) # type: ignore ) ), @@ -129,7 +129,7 @@ def input_fields_to_list(input_fields): ( "args", GraphQLField( - type=GraphQLNonNull( + type_=GraphQLNonNull( GraphQLList(GraphQLNonNull(__InputValue)) # type: ignore ), resolver=lambda directive, *args: input_fields_to_list( @@ -140,7 +140,7 @@ def input_fields_to_list(input_fields): ( "onOperation", GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), + type_=GraphQLNonNull(GraphQLBoolean), deprecation_reason="Use `locations`.", resolver=lambda directive, *args: set(directive.locations) & _on_operation_locations, @@ -149,7 +149,7 @@ def input_fields_to_list(input_fields): ( "onFragment", GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), + type_=GraphQLNonNull(GraphQLBoolean), deprecation_reason="Use `locations`.", resolver=lambda directive, *args: set(directive.locations) & _on_fragment_locations, @@ -158,7 +158,7 @@ def input_fields_to_list(input_fields): ( "onField", GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), + type_=GraphQLNonNull(GraphQLBoolean), deprecation_reason="Use `locations`.", resolver=lambda directive, *args: set(directive.locations) & _on_field_locations, @@ -421,7 +421,7 @@ def input_fields(type, info): ( "kind", GraphQLField( - type=GraphQLNonNull(__TypeKind), # type: ignore + type_=GraphQLNonNull(__TypeKind), # type: ignore resolver=TypeFieldResolvers.kind, ), ), @@ -430,7 +430,7 @@ def input_fields(type, info): ( "fields", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Field)), # type: ignore + type_=GraphQLList(GraphQLNonNull(__Field)), # type: ignore args={ "includeDeprecated": GraphQLArgument( GraphQLBoolean, default_value=False @@ -442,21 +442,21 @@ def input_fields(type, info): ( "interfaces", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), # type: ignore + type_=GraphQLList(GraphQLNonNull(__Type)), # type: ignore resolver=TypeFieldResolvers.interfaces, ), ), ( "possibleTypes", GraphQLField( - type=GraphQLList(GraphQLNonNull(__Type)), # type: ignore + type_=GraphQLList(GraphQLNonNull(__Type)), # type: ignore resolver=TypeFieldResolvers.possible_types, ), ), ( "enumValues", GraphQLField( - type=GraphQLList(GraphQLNonNull(__EnumValue)), # type: ignore + type_=GraphQLList(GraphQLNonNull(__EnumValue)), # type: ignore args={ "includeDeprecated": GraphQLArgument( GraphQLBoolean, default_value=False @@ -468,15 +468,15 @@ def input_fields(type, info): ( "inputFields", GraphQLField( - type=GraphQLList(GraphQLNonNull(__InputValue)), # type: ignore + type_=GraphQLList(GraphQLNonNull(__InputValue)), # type: ignore resolver=TypeFieldResolvers.input_fields, ), ), ( "ofType", GraphQLField( - type=__Type, # type: ignore - resolver=lambda type, *_: getattr(type, "of_type", None), + type_=__Type, # type: ignore + resolver=lambda type_, *_: getattr(type_, "of_type", None), ), ), ] @@ -494,7 +494,7 @@ def input_fields(type, info): ( "args", GraphQLField( - type=GraphQLNonNull( + type_=GraphQLNonNull( GraphQLList(GraphQLNonNull(__InputValue)) # type: ignore ), resolver=lambda field, *_: input_fields_to_list(field.args), @@ -504,14 +504,14 @@ def input_fields(type, info): ( "isDeprecated", GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), + type_=GraphQLNonNull(GraphQLBoolean), resolver=lambda field, *_: bool(field.deprecation_reason), ), ), ( "deprecationReason", GraphQLField( - type=GraphQLString, + type_=GraphQLString, resolver=lambda field, *_: field.deprecation_reason, ), ), @@ -532,7 +532,7 @@ def input_fields(type, info): ( "defaultValue", GraphQLField( - type=GraphQLString, + type_=GraphQLString, resolver=lambda input_val, *_: None if input_val.default_value is None else print_ast(ast_from_value(input_val.default_value, input_val)), @@ -554,14 +554,14 @@ def input_fields(type, info): ( "isDeprecated", GraphQLField( - type=GraphQLNonNull(GraphQLBoolean), + type_=GraphQLNonNull(GraphQLBoolean), resolver=lambda field, *_: bool(field.deprecation_reason), ), ), ( "deprecationReason", GraphQLField( - type=GraphQLString, + type_=GraphQLString, resolver=lambda enum_value, *_: enum_value.deprecation_reason, ), ), @@ -644,14 +644,14 @@ def input_fields(type, info): SchemaMetaFieldDef = GraphQLField( # name='__schema', - type=GraphQLNonNull(__Schema), + type_=GraphQLNonNull(__Schema), description="Access the current type schema of this server.", resolver=lambda source, info, **args: info.schema, args={}, ) TypeMetaFieldDef = GraphQLField( - type=__Type, + type_=__Type, # name='__type', description="Request the type information of a single type.", args={"name": GraphQLArgument(GraphQLNonNull(GraphQLString))}, @@ -659,7 +659,7 @@ def input_fields(type, info): ) TypeNameMetaFieldDef = GraphQLField( - type=GraphQLNonNull(GraphQLString), + type_=GraphQLNonNull(GraphQLString), # name='__typename', description="The name of the current Object type at runtime.", resolver=lambda source, info, **args: info.parent_type.name, diff --git a/graphql/type/schema.py b/graphql/type/schema.py index 697a8ae9..89cdb4c7 100644 --- a/graphql/type/schema.py +++ b/graphql/type/schema.py @@ -3,20 +3,22 @@ except ImportError: # Python < 3.3 from collections import Iterable -from .definition import GraphQLObjectType +from collections import namedtuple +from typing import Dict, Union, List, Optional + +from .definition import ( + GraphQLNamedType, + GraphQLInterfaceType, + GraphQLObjectType, + GraphQLUnionType, + GraphQLType, +) from .directives import GraphQLDirective, specified_directives from .introspection import IntrospectionSchema from .typemap import GraphQLTypeMap -# Necessary for static type checking -if False: # flake8: noqa - from .definition import ( - GraphQLNamedType, - GraphQLInterfaceType, - GraphQLUnionType, - GraphQLType, - ) - from typing import Dict, Union, List, Optional + +InterfaceImplementations = namedtuple("InterfaceImplementations", "objects, interfaces") class GraphQLSchema(object): @@ -101,7 +103,7 @@ def __init__( ) # type: List[GraphQLNamedType] if types: initial_types += types - self._type_map = GraphQLTypeMap(initial_types) # type: GraphQLTypeMap + self._type_map = GraphQLTypeMap(initial_types) def get_query_type(self): # type: () -> GraphQLObjectType diff --git a/graphql/type/tests/test_definition.py b/graphql/type/tests/test_definition.py index 944694ed..089309c4 100644 --- a/graphql/type/tests/test_definition.py +++ b/graphql/type/tests/test_definition.py @@ -74,7 +74,7 @@ "Subscription", { "articleSubscribe": GraphQLField( - args={"id": GraphQLArgument(GraphQLString)}, type=BlogArticle + args={"id": GraphQLArgument(GraphQLString)}, type_=BlogArticle ) }, ) @@ -169,7 +169,7 @@ def test_defines_an_object_type_with_deprecated_field(): "foo", fields={ "bar": GraphQLField( - type=GraphQLString, deprecation_reason="A terrible reason" + type_=GraphQLString, deprecation_reason="A terrible reason" ) }, ) @@ -198,7 +198,7 @@ def test_includes_nested_input_objects_in_the_map(): name="SomeMutation", fields={ "mutateSomething": GraphQLField( - type=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} + type_=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} ) }, ) @@ -206,7 +206,7 @@ def test_includes_nested_input_objects_in_the_map(): name="SomeSubscription", fields={ "subscribeToSomething": GraphQLField( - type=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} + type_=BlogArticle, args={"input": GraphQLArgument(SomeInputObject)} ) }, ) diff --git a/graphql/type/tests/test_enum_type.py b/graphql/type/tests/test_enum_type.py index 3feb2fdd..7f29b8dd 100644 --- a/graphql/type/tests/test_enum_type.py +++ b/graphql/type/tests/test_enum_type.py @@ -38,7 +38,7 @@ def get_first(args, *keys): name="Query", fields={ "colorEnum": GraphQLField( - type=ColorType, + type_=ColorType, args={ "fromEnum": GraphQLArgument(ColorType), "fromInt": GraphQLArgument(GraphQLInt), @@ -49,7 +49,7 @@ def get_first(args, *keys): ), ), "colorInt": GraphQLField( - type=GraphQLInt, + type_=GraphQLInt, args={ "fromEnum": GraphQLArgument(ColorType), "fromInt": GraphQLArgument(GraphQLInt), @@ -63,7 +63,7 @@ def get_first(args, *keys): name="Mutation", fields={ "favoriteEnum": GraphQLField( - type=ColorType, + type_=ColorType, args={"color": GraphQLArgument(ColorType)}, resolver=lambda value, info, **args: args.get("color"), ) @@ -74,7 +74,7 @@ def get_first(args, *keys): name="Subscription", fields={ "subscribeToEnum": GraphQLField( - type=ColorType, + type_=ColorType, args={"color": GraphQLArgument(ColorType)}, resolver=lambda value, info, **args: Observable.from_([args.get("color")]), ) @@ -187,9 +187,9 @@ def test_accepts_enum_literals_as_input_arguments_to_subscriptions(): allow_subscriptions=True, ) assert isinstance(result, Observable) - l = [] - result.subscribe(l.append) - result = l[0] + lit = [] + result.subscribe(lit.append) + result = lit[0] assert not result.errors assert result.data == {"subscribeToEnum": "GREEN"} diff --git a/graphql/type/tests/test_introspection.py b/graphql/type/tests/test_introspection.py index 35df33be..8085189b 100644 --- a/graphql/type/tests/test_introspection.py +++ b/graphql/type/tests/test_introspection.py @@ -798,7 +798,7 @@ def test_introspects_on_input_object(): "TestType", { "field": GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={"complex": GraphQLArgument(TestInputObject)}, resolver=lambda obj, info, **args: json.dumps(args.get("complex")), ) diff --git a/graphql/type/tests/test_schema.py b/graphql/type/tests/test_schema.py index 5f7b56dc..d27b50cb 100644 --- a/graphql/type/tests/test_schema.py +++ b/graphql/type/tests/test_schema.py @@ -12,7 +12,7 @@ name="Interface", fields={ "field_name": GraphQLField( - type=GraphQLString, resolver=lambda *_: implementing_type + type_=GraphQLString, resolver=lambda *_: implementing_type ) }, ) @@ -20,7 +20,7 @@ implementing_type = GraphQLObjectType( name="Object", interfaces=[interface_type], - fields={"field_name": GraphQLField(type=GraphQLString, resolver=lambda *_: "")}, + fields={"field_name": GraphQLField(type_=GraphQLString, resolver=lambda *_: "")}, ) @@ -28,7 +28,7 @@ query=GraphQLObjectType( name="Query", fields={ - "get_object": GraphQLField(type=interface_type, resolver=lambda *_: {}) + "get_object": GraphQLField(type_=interface_type, resolver=lambda *_: {}) }, ) ) diff --git a/graphql/type/tests/test_validation.py b/graphql/type/tests/test_validation.py index c1f1daf6..b8467bcf 100644 --- a/graphql/type/tests/test_validation.py +++ b/graphql/type/tests/test_validation.py @@ -1160,7 +1160,7 @@ def schema_with_arg_of_type(arg_type): name="BadObject", fields={ "badField": GraphQLField( - type=GraphQLString, args={"badArg": GraphQLArgument(arg_type)} + type_=GraphQLString, args={"badArg": GraphQLArgument(arg_type)} ) }, ) @@ -1214,7 +1214,7 @@ def schema_with_input_field_of_type(input_field_type): name="Query", fields={ "f": GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={"badArg": GraphQLArgument(BadInputObjectType)}, ) }, @@ -1352,7 +1352,7 @@ def test_accepts_an_object_which_implements_an_interface(self): resolve_type=_none, fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) @@ -1362,7 +1362,7 @@ def test_accepts_an_object_which_implements_an_interface(self): interfaces=[AnotherInterface], fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) @@ -1377,7 +1377,7 @@ def test_accepts_an_object_which_implements_an_interface_along_with_more_fields( resolve_type=_none, fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) @@ -1387,7 +1387,7 @@ def test_accepts_an_object_which_implements_an_interface_along_with_more_fields( interfaces=[AnotherInterface], fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ), "anotherfield": GraphQLField(GraphQLString), }, @@ -1403,7 +1403,7 @@ def test_accepts_an_object_which_implements_an_interface_field_along_with_more_a resolve_type=_none, fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) @@ -1413,7 +1413,7 @@ def test_accepts_an_object_which_implements_an_interface_field_along_with_more_a interfaces=[AnotherInterface], fields={ "field": GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={ "input": GraphQLArgument(GraphQLString), "anotherInput": GraphQLArgument(GraphQLString), @@ -1432,7 +1432,7 @@ def test_rejects_an_object_which_implements_an_interface_field_along_with_additi resolve_type=_none, fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) @@ -1442,7 +1442,7 @@ def test_rejects_an_object_which_implements_an_interface_field_along_with_additi interfaces=[AnotherInterface], fields={ "field": GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={ "input": GraphQLArgument(GraphQLString), "anotherInput": GraphQLArgument(GraphQLNonNull(GraphQLString)), @@ -1466,7 +1466,7 @@ def test_rejects_an_object_missing_an_interface_field(self): resolve_type=_none, fields={ "field": GraphQLField( - type=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} + type_=GraphQLString, args={"input": GraphQLArgument(GraphQLString)} ) }, ) diff --git a/graphql/type/typemap.py b/graphql/type/typemap.py index 427417ca..0cc08844 100644 --- a/graphql/type/typemap.py +++ b/graphql/type/typemap.py @@ -1,6 +1,8 @@ from collections import OrderedDict, defaultdict from functools import reduce +from typing import cast + from ..utils.type_comparators import is_equal_type, is_type_sub_type_of from .definition import ( GraphQLArgument, @@ -18,6 +20,7 @@ # Necessary for static type checking if False: # flake8: noqa from ..type.definition import GraphQLNamedType + from ..type.schema import GraphQLSchema from typing import List, Union, Dict, Set, DefaultDict @@ -38,10 +41,10 @@ def __init__(self, types): self._implementations[interface.name].append(gql_type) # Enforce correct interface implementations. - for type in self.values(): - if isinstance(type, GraphQLObjectType): - for interface in type.interfaces: - self.assert_object_implements_interface(self, type, interface) + for type_ in self.values(): + if isinstance(type_, GraphQLObjectType): + for interface in type_.interfaces: + self.assert_object_implements_interface(self, type_, interface) def get_possible_types(self, abstract_type): # type: (Union[GraphQLInterfaceType, GraphQLUnionType]) -> List[GraphQLObjectType] @@ -73,66 +76,66 @@ def is_possible_type( return possible_type.name in self._possible_type_map[abstract_type.name] @classmethod - def reducer(cls, map, type): + def reducer(cls, map_, type_): # type: (Dict, Union[GraphQLNamedType, GraphQLList, GraphQLNonNull]) -> Dict - if not type: - return map + if not type_: + return map_ - if isinstance(type, (GraphQLList, GraphQLNonNull)): - return cls.reducer(map, type.of_type) + if isinstance(type_, (GraphQLList, GraphQLNonNull)): + return cls.reducer(map_, type_.of_type) - if type.name in map: - assert map[type.name] == type, ( + if type_.name in map_: + assert map_[type_.name] == type_, ( 'Schema must contain unique named types but contains multiple types named "{}".' - ).format(type.name) + ).format(type_.name) - return map + return map_ - map[type.name] = type # type: ignore + map_[type_.name] = type_ # type: ignore - reduced_map = map + reduced_map = map_ - if isinstance(type, (GraphQLUnionType)): - for t in type.types: + if isinstance(type_, GraphQLUnionType): + for t in type_.types: reduced_map = cls.reducer(reduced_map, t) - if isinstance(type, GraphQLObjectType): - for t in type.interfaces: + if isinstance(type_, GraphQLObjectType): + for t in type_.interfaces: reduced_map = cls.reducer(reduced_map, t) if isinstance( - type, (GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType) + type_, (GraphQLObjectType, GraphQLInterfaceType, GraphQLInputObjectType) ): - field_map = type.fields - type_is_input = isinstance(type, GraphQLInputObjectType) + field_map = type_.fields + type_is_input = isinstance(type_, GraphQLInputObjectType) for field_name, field in field_map.items(): if type_is_input: assert isinstance( field, GraphQLInputObjectField ), "{}.{} must be an instance of GraphQLInputObjectField.".format( - type, field_name + type_, field_name ) assert is_input_type( field.type ), "{}.{} field type must be Input Type but got: {}.".format( - type, field_name, field.type + type_, field_name, field.type ) else: assert is_output_type( field.type ), "{}.{} field type must be Output Type but got: {}.".format( - type, field_name, field.type + type_, field_name, field.type ) for arg_name, arg in field.args.items(): assert isinstance( arg, (GraphQLArgument, GraphQLArgument) ), "{}.{}({}:) argument must be an instance of GraphQLArgument.".format( - type, field_name, arg_name + type_, field_name, arg_name ) assert is_input_type( arg.type ), "{}.{}({}:) argument type must be Input Type but got: {}.".format( - type, field_name, arg_name, arg.type + type_, field_name, arg_name, arg.type ) reduced_map = cls.reducer(reduced_map, arg.type) @@ -143,7 +146,7 @@ def reducer(cls, map, type): @classmethod def assert_object_implements_interface( cls, - schema, # type: GraphQLTypeMap + schema, # type: Union[GraphQLTypeMap, GraphQLSchema] object, # type: GraphQLObjectType interface, # type: GraphQLInterfaceType ): @@ -161,8 +164,8 @@ def assert_object_implements_interface( ) assert is_type_sub_type_of( - schema, object_field.type, interface_field.type - ), ('{}.{} expects type "{}" but {}.{} provides type "{}".').format( + cast("GraphQLSchema", schema), object_field.type, interface_field.type + ), '{}.{} expects type "{}" but {}.{} provides type "{}".'.format( interface, field_name, interface_field.type, diff --git a/graphql/utils/build_ast_schema.py b/graphql/utils/build_ast_schema.py index 8d28f4be..1a2dd8e4 100644 --- a/graphql/utils/build_ast_schema.py +++ b/graphql/utils/build_ast_schema.py @@ -217,7 +217,7 @@ def make_field_def_map(definition): ( f.name.value, GraphQLField( - type=produce_type_def(f.type), + type_=produce_type_def(f.type), args=make_input_values(f.arguments, GraphQLArgument), deprecation_reason=get_deprecation_reason(f.directives), ), @@ -233,7 +233,7 @@ def make_input_values(values, cls): ( value.name.value, cls( - type=produce_type_def(value.type), + type_=produce_type_def(value.type), default_value=value_from_ast( value.default_value, produce_type_def(value.type) ), diff --git a/graphql/utils/build_client_schema.py b/graphql/utils/build_client_schema.py index b499c02f..152abaaf 100644 --- a/graphql/utils/build_client_schema.py +++ b/graphql/utils/build_client_schema.py @@ -225,7 +225,7 @@ def build_field_def_map(type_introspection): ( f["name"], GraphQLField( - type=get_output_type(f["type"]), + type_=get_output_type(f["type"]), description=f.get("description"), resolver=no_execution, deprecation_reason=f.get("deprecationReason"), @@ -254,7 +254,7 @@ def build_input_value_def_map(input_value_introspection, argument_type): def build_input_value(input_value_introspection, argument_type): input_value = argument_type( description=input_value_introspection.get("description"), - type=get_input_type(input_value_introspection["type"]), + type_=get_input_type(input_value_introspection["type"]), default_value=build_default_value(input_value_introspection), ) return input_value diff --git a/graphql/utils/tests/test_build_client_schema.py b/graphql/utils/tests/test_build_client_schema.py index decc2852..a6f73078 100644 --- a/graphql/utils/tests/test_build_client_schema.py +++ b/graphql/utils/tests/test_build_client_schema.py @@ -81,7 +81,7 @@ def test_builds_a_simple_schema_with_both_operation_types(): description="This is a simple subscription type", fields={ "string": GraphQLField( - type=GraphQLString, description="This is a string field" + type_=GraphQLString, description="This is a string field" ) }, ) @@ -420,10 +420,10 @@ def test_builds_a_schema_with_an_input_object(): fields={ "geocode": GraphQLField( description="Get a geocode from an address", - type=GraphQLString, + type_=GraphQLString, args={ "address": GraphQLArgument( - description="The address to lookup", type=AddressType + description="The address to lookup", type_=AddressType ) }, ) @@ -499,7 +499,7 @@ def test_builds_a_schema_with_custom_directives(): description="This is a simple type", fields={ "string": GraphQLField( - type=GraphQLString, description="This is a string field" + type_=GraphQLString, description="This is a string field" ) }, ), @@ -586,14 +586,14 @@ def test_builds_a_schema_aware_of_deprecation(): ( "shinyString", GraphQLField( - type=GraphQLString, + type_=GraphQLString, description="This is a shiny string field", ), ), ( "deprecatedString", GraphQLField( - type=GraphQLString, + type_=GraphQLString, description="This is a deprecated string field", deprecation_reason="Use shinyString", ), @@ -601,7 +601,7 @@ def test_builds_a_schema_aware_of_deprecation(): ( "color", GraphQLField( - type=GraphQLEnumType( + type_=GraphQLEnumType( name="Color", values=OrderedDict( [ diff --git a/graphql/utils/tests/test_schema_printer.py b/graphql/utils/tests/test_schema_printer.py index 832676ee..951d00c4 100644 --- a/graphql/utils/tests/test_schema_printer.py +++ b/graphql/utils/tests/test_schema_printer.py @@ -147,7 +147,7 @@ def test_prints_object_field(): def test_prints_string_field_with_int_arg(): output = print_single_field_schema( - GraphQLField(type=GraphQLString, args={"argOne": GraphQLArgument(GraphQLInt)}) + GraphQLField(type_=GraphQLString, args={"argOne": GraphQLArgument(GraphQLInt)}) ) assert ( output @@ -166,7 +166,7 @@ def test_prints_string_field_with_int_arg(): def test_prints_string_field_with_int_arg_with_default(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={"argOne": GraphQLArgument(GraphQLInt, default_value=2)}, ) ) @@ -187,7 +187,7 @@ def test_prints_string_field_with_int_arg_with_default(): def test_prints_string_field_with_non_null_int_arg(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args={"argOne": GraphQLArgument(GraphQLNonNull(GraphQLInt))}, ) ) @@ -208,7 +208,7 @@ def test_prints_string_field_with_non_null_int_arg(): def test_prints_string_field_with_multiple_args(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args=OrderedDict( [ ("argOne", GraphQLArgument(GraphQLInt)), @@ -235,7 +235,7 @@ def test_prints_string_field_with_multiple_args(): def test_prints_string_field_with_multiple_args_first_is_default(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args=OrderedDict( [ ("argOne", GraphQLArgument(GraphQLInt, default_value=1)), @@ -263,7 +263,7 @@ def test_prints_string_field_with_multiple_args_first_is_default(): def test_prints_string_field_with_multiple_args_second_is_default(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args=OrderedDict( [ ("argOne", GraphQLArgument(GraphQLInt)), @@ -291,7 +291,7 @@ def test_prints_string_field_with_multiple_args_second_is_default(): def test_prints_string_field_with_multiple_args_last_is_default(): output = print_single_field_schema( GraphQLField( - type=GraphQLString, + type_=GraphQLString, args=OrderedDict( [ ("argOne", GraphQLArgument(GraphQLInt)), diff --git a/graphql/utils/type_comparators.py b/graphql/utils/type_comparators.py index dcda87db..dec4d846 100644 --- a/graphql/utils/type_comparators.py +++ b/graphql/utils/type_comparators.py @@ -1,16 +1,22 @@ from ..type.definition import ( + GraphQLAbstractType, GraphQLInterfaceType, GraphQLList, GraphQLNonNull, GraphQLObjectType, + GraphQLType, GraphQLUnionType, is_abstract_type, + is_interface_type, + is_list_type, + is_non_null_type, + is_object_type, ) +from typing import cast + # Necessary for static type checking if False: # flake8: noqa - from ..type.definition import GraphQLScalarType - from ..type.typemap import GraphQLTypeMap from ..type.schema import GraphQLSchema from typing import Union @@ -28,37 +34,58 @@ def is_equal_type(type_a, type_b): return False -def is_type_sub_type_of(schema, maybe_subtype, super_type): - # type: (Union[GraphQLSchema, GraphQLTypeMap], GraphQLScalarType, GraphQLScalarType) -> bool +def is_type_sub_type_of( + schema, # type: GraphQLSchema + maybe_subtype, # type: GraphQLType + super_type, # type: GraphQLType +): + # type: (...) -> bool + """Check whether a type is subtype of another type in a given schema. + Provided a type and a super type, return true if the first type is either equal or + a subset of the second super type (covariant). + """ + # Equivalent type is a valid subtype if maybe_subtype is super_type: return True - if isinstance(super_type, GraphQLNonNull): - if isinstance(maybe_subtype, GraphQLNonNull): + # If super_type is non-null, maybe_subtype must also be non-null. + if is_non_null_type(super_type): + if is_non_null_type(maybe_subtype): return is_type_sub_type_of( - schema, maybe_subtype.of_type, super_type.of_type + schema, + cast(GraphQLNonNull, maybe_subtype).of_type, + cast(GraphQLNonNull, super_type).of_type, ) return False - elif isinstance(maybe_subtype, GraphQLNonNull): - return is_type_sub_type_of(schema, maybe_subtype.of_type, super_type) - - if isinstance(super_type, GraphQLList): - if isinstance(maybe_subtype, GraphQLList): + elif is_non_null_type(maybe_subtype): + # If super_type is nullable, maybe_subtype may be non-null or nullable. + return is_type_sub_type_of( + schema, cast(GraphQLNonNull, maybe_subtype).of_type, super_type + ) + + # If super_type type is a list, maybeSubType type must also be a list. + if is_list_type(super_type): + if is_list_type(maybe_subtype): return is_type_sub_type_of( - schema, maybe_subtype.of_type, super_type.of_type + schema, + cast(GraphQLList, maybe_subtype).of_type, + cast(GraphQLList, super_type).of_type, ) return False - elif isinstance(maybe_subtype, GraphQLList): + elif is_list_type(maybe_subtype): + # If super_type is not a list, maybe_subtype must also be not a list. return False - if ( + # If super_type type is abstract, check if it is super type of maybe_subtype. + # Otherwise, the child type is not a valid subtype of the parent type. + return ( is_abstract_type(super_type) - and isinstance(maybe_subtype, GraphQLObjectType) - and schema.is_possible_type(super_type, maybe_subtype) - ): - return True - - return False + and (is_interface_type(maybe_subtype) or is_object_type(maybe_subtype)) + and schema.is_possible_type( + cast(GraphQLAbstractType, super_type), + cast(GraphQLObjectType, maybe_subtype), + ) + ) def do_types_overlap( diff --git a/graphql/validation/rules/overlapping_fields_can_be_merged.py b/graphql/validation/rules/overlapping_fields_can_be_merged.py index 9de79be0..d76dfc52 100644 --- a/graphql/validation/rules/overlapping_fields_can_be_merged.py +++ b/graphql/validation/rules/overlapping_fields_can_be_merged.py @@ -1,6 +1,8 @@ import itertools from collections import OrderedDict +from typing import cast + from ...error import GraphQLError from ...language import ast from ...language.printer import print_ast @@ -10,8 +12,11 @@ GraphQLList, GraphQLNonNull, GraphQLObjectType, + GraphQLOutputType, get_named_type, is_leaf_type, + is_list_type, + is_non_null_type, ) from ...utils.type_comparators import is_equal_type from ...utils.type_from_ast import type_from_ast @@ -28,7 +33,7 @@ InlineFragment, SelectionSet, ) - from ...type.definition import GraphQLField, GraphQLScalarType + from ...type.definition import GraphQLField from typing import List, Union, Any, Optional, Dict, Tuple @@ -545,7 +550,7 @@ def _find_conflict( # Two field calls must have the same arguments. if not _same_arguments(ast1.arguments, ast2.arguments): - return ((response_name, "they have differing arguments"), [ast1], [ast2]) + return (response_name, "they have differing arguments"), [ast1], [ast2] if type1 and type2 and do_types_conflict(type1, type2): return ( @@ -685,37 +690,42 @@ def _subfield_conflicts( if conflicts: return ( (response_name, [conflict[0] for conflict in conflicts]), # type: ignore - tuple(itertools.chain([ast1], *[conflict[1] for conflict in conflicts])), - tuple(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])), + list(itertools.chain([ast1], *[conflict[1] for conflict in conflicts])), + list(itertools.chain([ast2], *[conflict[2] for conflict in conflicts])), ) return None def do_types_conflict(type1, type2): - # type: (GraphQLScalarType, GraphQLScalarType) -> bool - if isinstance(type1, GraphQLList): - if isinstance(type2, GraphQLList): - return do_types_conflict(type1.of_type, type2.of_type) - return True - - if isinstance(type2, GraphQLList): - if isinstance(type1, GraphQLList): - return do_types_conflict(type1.of_type, type2.of_type) - return True + # type: (GraphQLOutputType, GraphQLOutputType) -> bool + """Check whether two types conflict - if isinstance(type1, GraphQLNonNull): - if isinstance(type2, GraphQLNonNull): - return do_types_conflict(type1.of_type, type2.of_type) + Two types conflict if both types could not apply to a value simultaneously. + Composite types are ignored as their individual field types will be compared later + recursively. However List and Non-Null types must match. + """ + if is_list_type(type1): + return ( + do_types_conflict( + cast(GraphQLList, type1).of_type, cast(GraphQLList, type2).of_type + ) + if is_list_type(type2) + else True + ) + if is_list_type(type2): return True - - if isinstance(type2, GraphQLNonNull): - if isinstance(type1, GraphQLNonNull): - return do_types_conflict(type1.of_type, type2.of_type) + if is_non_null_type(type1): + return ( + do_types_conflict( + cast(GraphQLNonNull, type1).of_type, cast(GraphQLNonNull, type2).of_type + ) + if is_non_null_type(type2) + else True + ) + if is_non_null_type(type2): return True - if is_leaf_type(type1) or is_leaf_type(type2): - return type1 != type2 - + return type1 is not type2 return False diff --git a/tests/starwars/starwars_schema.py b/tests/starwars/starwars_schema.py index a5c2a6f0..52e59e2a 100644 --- a/tests/starwars/starwars_schema.py +++ b/tests/starwars/starwars_schema.py @@ -100,7 +100,7 @@ "episode": GraphQLArgument( description="If omitted, returns the hero of the whole saga. If " "provided, returns the hero of that particular episode.", - type=episodeEnum, + type_=episodeEnum, ) }, resolver=lambda root, info, **args: getHero(args.get("episode")), @@ -109,7 +109,7 @@ humanType, args={ "id": GraphQLArgument( - description="id of the human", type=GraphQLNonNull(GraphQLString) + description="id of the human", type_=GraphQLNonNull(GraphQLString) ) }, resolver=lambda root, info, **args: getHuman(args["id"]), @@ -118,7 +118,7 @@ droidType, args={ "id": GraphQLArgument( - description="id of the droid", type=GraphQLNonNull(GraphQLString) + description="id of the droid", type_=GraphQLNonNull(GraphQLString) ) }, resolver=lambda root, info, **args: getDroid(args["id"]), diff --git a/tox.ini b/tox.ini index afe8751e..3cf0d5de 100644 --- a/tox.ini +++ b/tox.ini @@ -22,7 +22,7 @@ commands = [testenv:mypy] basepython=python3.8 deps = - mypy==0.761 + mypy==0.770 commands = mypy graphql --ignore-missing-imports