mirror of
https://github.com/graphql-python/graphene.git
synced 2025-04-25 12:03:41 +03:00
Use latest graphql-core 3.1.0b1 instead of 3.0.3
Adapt Schema, because there is no type reducer in core 3.1 any more.
This commit is contained in:
parent
ffb7701466
commit
5e6f68957e
|
@ -1,2 +1,2 @@
|
||||||
[settings]
|
[settings]
|
||||||
known_third_party = aniso8601,graphql,graphql_relay,promise,pytest,pytz,pyutils,setuptools,six,snapshottest,sphinx_graphene_theme
|
known_third_party = aniso8601,graphql,graphql_relay,promise,pytest,pytz,pyutils,setuptools,snapshottest,sphinx_graphene_theme
|
||||||
|
|
|
@ -31,7 +31,16 @@ snapshots["test_correctly_refetches_xwing 1"] = {
|
||||||
|
|
||||||
snapshots[
|
snapshots[
|
||||||
"test_str_schema 1"
|
"test_str_schema 1"
|
||||||
] = '''"""A faction in the Star Wars saga"""
|
] = '''type Query {
|
||||||
|
rebels: Faction
|
||||||
|
empire: Faction
|
||||||
|
node(
|
||||||
|
"""The ID of the object"""
|
||||||
|
id: ID!
|
||||||
|
): Node
|
||||||
|
}
|
||||||
|
|
||||||
|
"""A faction in the Star Wars saga"""
|
||||||
type Faction implements Node {
|
type Faction implements Node {
|
||||||
"""The ID of the object"""
|
"""The ID of the object"""
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -43,28 +52,20 @@ type Faction implements Node {
|
||||||
ships(before: String = null, after: String = null, first: Int = null, last: Int = null): ShipConnection
|
ships(before: String = null, after: String = null, first: Int = null, last: Int = null): ShipConnection
|
||||||
}
|
}
|
||||||
|
|
||||||
input IntroduceShipInput {
|
|
||||||
shipName: String!
|
|
||||||
factionId: String!
|
|
||||||
clientMutationId: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type IntroduceShipPayload {
|
|
||||||
ship: Ship
|
|
||||||
faction: Faction
|
|
||||||
clientMutationId: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type Mutation {
|
|
||||||
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
|
|
||||||
}
|
|
||||||
|
|
||||||
"""An object with an ID"""
|
"""An object with an ID"""
|
||||||
interface Node {
|
interface Node {
|
||||||
"""The ID of the object"""
|
"""The ID of the object"""
|
||||||
id: ID!
|
id: ID!
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type ShipConnection {
|
||||||
|
"""Pagination data for this connection."""
|
||||||
|
pageInfo: PageInfo!
|
||||||
|
|
||||||
|
"""Contains the nodes in this connection."""
|
||||||
|
edges: [ShipEdge]!
|
||||||
|
}
|
||||||
|
|
||||||
"""
|
"""
|
||||||
The Relay compliant `PageInfo` type, containing data necessary to paginate this connection.
|
The Relay compliant `PageInfo` type, containing data necessary to paginate this connection.
|
||||||
"""
|
"""
|
||||||
|
@ -82,13 +83,13 @@ type PageInfo {
|
||||||
endCursor: String
|
endCursor: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type Query {
|
"""A Relay edge containing a `Ship` and its cursor."""
|
||||||
rebels: Faction
|
type ShipEdge {
|
||||||
empire: Faction
|
"""The item at the end of the edge"""
|
||||||
node(
|
node: Ship
|
||||||
"""The ID of the object"""
|
|
||||||
id: ID!
|
"""A cursor for use in pagination"""
|
||||||
): Node
|
cursor: String!
|
||||||
}
|
}
|
||||||
|
|
||||||
"""A ship in the Star Wars saga"""
|
"""A ship in the Star Wars saga"""
|
||||||
|
@ -100,20 +101,19 @@ type Ship implements Node {
|
||||||
name: String
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
type ShipConnection {
|
type Mutation {
|
||||||
"""Pagination data for this connection."""
|
introduceShip(input: IntroduceShipInput!): IntroduceShipPayload
|
||||||
pageInfo: PageInfo!
|
|
||||||
|
|
||||||
"""Contains the nodes in this connection."""
|
|
||||||
edges: [ShipEdge]!
|
|
||||||
}
|
}
|
||||||
|
|
||||||
"""A Relay edge containing a `Ship` and its cursor."""
|
type IntroduceShipPayload {
|
||||||
type ShipEdge {
|
ship: Ship
|
||||||
"""The item at the end of the edge"""
|
faction: Faction
|
||||||
node: Ship
|
clientMutationId: String
|
||||||
|
}
|
||||||
|
|
||||||
"""A cursor for use in pagination"""
|
input IntroduceShipInput {
|
||||||
cursor: String!
|
shipName: String!
|
||||||
|
factionId: String!
|
||||||
|
clientMutationId: String
|
||||||
}
|
}
|
||||||
'''
|
'''
|
||||||
|
|
|
@ -42,7 +42,7 @@ from .utils.resolve_only_args import resolve_only_args
|
||||||
from .utils.module_loading import lazy_import
|
from .utils.module_loading import lazy_import
|
||||||
|
|
||||||
|
|
||||||
VERSION = (3, 0, 0, "alpha", 1)
|
VERSION = (3, 0, 0, "beta", 0)
|
||||||
|
|
||||||
|
|
||||||
__version__ = get_version(VERSION)
|
__version__ = get_version(VERSION)
|
||||||
|
|
|
@ -183,6 +183,12 @@ def test_str_schema():
|
||||||
name: String
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
|
"""An object with an ID"""
|
||||||
|
interface Node {
|
||||||
|
"""The ID of the object"""
|
||||||
|
id: ID!
|
||||||
|
}
|
||||||
|
|
||||||
type MyOtherNode implements Node {
|
type MyOtherNode implements Node {
|
||||||
"""The ID of the object"""
|
"""The ID of the object"""
|
||||||
id: ID!
|
id: ID!
|
||||||
|
@ -191,12 +197,6 @@ def test_str_schema():
|
||||||
extraField: String
|
extraField: String
|
||||||
}
|
}
|
||||||
|
|
||||||
"""An object with an ID"""
|
|
||||||
interface Node {
|
|
||||||
"""The ID of the object"""
|
|
||||||
id: ID!
|
|
||||||
}
|
|
||||||
|
|
||||||
type RootQuery {
|
type RootQuery {
|
||||||
first: String
|
first: String
|
||||||
node(
|
node(
|
||||||
|
|
|
@ -59,9 +59,12 @@ def test_str_schema_correct():
|
||||||
query: RootQuery
|
query: RootQuery
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BasePhoto {
|
type User implements Node {
|
||||||
"""The width of the photo in pixels"""
|
"""The ID of the object"""
|
||||||
width: Int
|
id: ID!
|
||||||
|
|
||||||
|
"""The full name of the user"""
|
||||||
|
name: String
|
||||||
}
|
}
|
||||||
|
|
||||||
interface Node {
|
interface Node {
|
||||||
|
@ -77,20 +80,17 @@ def test_str_schema_correct():
|
||||||
width: Int
|
width: Int
|
||||||
}
|
}
|
||||||
|
|
||||||
|
interface BasePhoto {
|
||||||
|
"""The width of the photo in pixels"""
|
||||||
|
width: Int
|
||||||
|
}
|
||||||
|
|
||||||
type RootQuery {
|
type RootQuery {
|
||||||
node(
|
node(
|
||||||
"""The ID of the object"""
|
"""The ID of the object"""
|
||||||
id: ID!
|
id: ID!
|
||||||
): Node
|
): Node
|
||||||
}
|
}
|
||||||
|
|
||||||
type User implements Node {
|
|
||||||
"""The ID of the object"""
|
|
||||||
id: ID!
|
|
||||||
|
|
||||||
"""The full name of the user"""
|
|
||||||
name: String
|
|
||||||
}
|
|
||||||
'''
|
'''
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -27,7 +27,7 @@ def test_issue():
|
||||||
graphene.Schema(query=Query)
|
graphene.Schema(query=Query)
|
||||||
|
|
||||||
assert str(exc_info.value) == (
|
assert str(exc_info.value) == (
|
||||||
"Query fields cannot be resolved:"
|
"Query fields cannot be resolved."
|
||||||
" IterableConnectionField type has to be a subclass of Connection."
|
" IterableConnectionField type has to be a subclass of Connection."
|
||||||
' Received "MyUnion".'
|
' Received "MyUnion".'
|
||||||
)
|
)
|
||||||
|
|
|
@ -3,8 +3,8 @@ from __future__ import absolute_import
|
||||||
import datetime
|
import datetime
|
||||||
|
|
||||||
from aniso8601 import parse_date, parse_datetime, parse_time
|
from aniso8601 import parse_date, parse_datetime, parse_time
|
||||||
from graphql import Undefined
|
from graphql.error import GraphQLError
|
||||||
from graphql.language import StringValueNode
|
from graphql.language import StringValueNode, print_ast
|
||||||
|
|
||||||
from .scalars import Scalar
|
from .scalars import Scalar
|
||||||
|
|
||||||
|
@ -20,25 +20,30 @@ class Date(Scalar):
|
||||||
def serialize(date):
|
def serialize(date):
|
||||||
if isinstance(date, datetime.datetime):
|
if isinstance(date, datetime.datetime):
|
||||||
date = date.date()
|
date = date.date()
|
||||||
assert isinstance(
|
if not isinstance(date, datetime.date):
|
||||||
date, datetime.date
|
raise GraphQLError("Date cannot represent value: {}".format(repr(date)))
|
||||||
), 'Received not compatible date "{}"'.format(repr(date))
|
|
||||||
return date.isoformat()
|
return date.isoformat()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_literal(cls, node):
|
def parse_literal(cls, node):
|
||||||
if isinstance(node, StringValueNode):
|
if not isinstance(node, StringValueNode):
|
||||||
return cls.parse_value(node.value)
|
raise GraphQLError(
|
||||||
|
"Date cannot represent non-string value: {}".format(print_ast(node))
|
||||||
|
)
|
||||||
|
return cls.parse_value(node.value)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_value(value):
|
def parse_value(value):
|
||||||
|
if isinstance(value, datetime.date):
|
||||||
|
return value
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise GraphQLError(
|
||||||
|
"Date cannot represent non-string value: {}".format(repr(value))
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
if isinstance(value, datetime.date):
|
return parse_date(value)
|
||||||
return value
|
|
||||||
elif isinstance(value, str):
|
|
||||||
return parse_date(value)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return Undefined
|
raise GraphQLError("Date cannot represent value: {}".format(repr(value)))
|
||||||
|
|
||||||
|
|
||||||
class DateTime(Scalar):
|
class DateTime(Scalar):
|
||||||
|
@ -50,25 +55,32 @@ class DateTime(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serialize(dt):
|
def serialize(dt):
|
||||||
assert isinstance(
|
if not isinstance(dt, (datetime.datetime, datetime.date)):
|
||||||
dt, (datetime.datetime, datetime.date)
|
raise GraphQLError("DateTime cannot represent value: {}".format(repr(dt)))
|
||||||
), 'Received not compatible datetime "{}"'.format(repr(dt))
|
|
||||||
return dt.isoformat()
|
return dt.isoformat()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_literal(cls, node):
|
def parse_literal(cls, node):
|
||||||
if isinstance(node, StringValueNode):
|
if not isinstance(node, StringValueNode):
|
||||||
return cls.parse_value(node.value)
|
raise GraphQLError(
|
||||||
|
"DateTime cannot represent non-string value: {}".format(print_ast(node))
|
||||||
|
)
|
||||||
|
return cls.parse_value(node.value)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_value(value):
|
def parse_value(value):
|
||||||
|
if isinstance(value, datetime.datetime):
|
||||||
|
return value
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise GraphQLError(
|
||||||
|
"DateTime cannot represent non-string value: {}".format(repr(value))
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
if isinstance(value, datetime.datetime):
|
return parse_datetime(value)
|
||||||
return value
|
|
||||||
elif isinstance(value, str):
|
|
||||||
return parse_datetime(value)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return Undefined
|
raise GraphQLError(
|
||||||
|
"DateTime cannot represent value: {}".format(repr(value))
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
class Time(Scalar):
|
class Time(Scalar):
|
||||||
|
@ -80,22 +92,27 @@ class Time(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def serialize(time):
|
def serialize(time):
|
||||||
assert isinstance(
|
if not isinstance(time, datetime.time):
|
||||||
time, datetime.time
|
raise GraphQLError("Time cannot represent value: {}".format(repr(time)))
|
||||||
), 'Received not compatible time "{}"'.format(repr(time))
|
|
||||||
return time.isoformat()
|
return time.isoformat()
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_literal(cls, node):
|
def parse_literal(cls, node):
|
||||||
if isinstance(node, StringValueNode):
|
if not isinstance(node, StringValueNode):
|
||||||
return cls.parse_value(node.value)
|
raise GraphQLError(
|
||||||
|
"Time cannot represent non-string value: {}".format(print_ast(node))
|
||||||
|
)
|
||||||
|
return cls.parse_value(node.value)
|
||||||
|
|
||||||
@classmethod
|
@classmethod
|
||||||
def parse_value(cls, value):
|
def parse_value(cls, value):
|
||||||
|
if isinstance(value, datetime.time):
|
||||||
|
return value
|
||||||
|
if not isinstance(value, str):
|
||||||
|
raise GraphQLError(
|
||||||
|
"Time cannot represent non-string value: {}".format(repr(value))
|
||||||
|
)
|
||||||
try:
|
try:
|
||||||
if isinstance(value, datetime.time):
|
return parse_time(value)
|
||||||
return value
|
|
||||||
elif isinstance(value, str):
|
|
||||||
return parse_time(value)
|
|
||||||
except ValueError:
|
except ValueError:
|
||||||
return Undefined
|
raise GraphQLError("Time cannot represent value: {}".format(repr(value)))
|
||||||
|
|
|
@ -1,4 +1,5 @@
|
||||||
from graphql import Undefined
|
from graphql import Undefined
|
||||||
|
|
||||||
from .mountedtype import MountedType
|
from .mountedtype import MountedType
|
||||||
from .structures import NonNull
|
from .structures import NonNull
|
||||||
from .utils import get_type
|
from .utils import get_type
|
||||||
|
|
|
@ -7,7 +7,6 @@ from graphql import (
|
||||||
graphql,
|
graphql,
|
||||||
graphql_sync,
|
graphql_sync,
|
||||||
introspection_types,
|
introspection_types,
|
||||||
is_type,
|
|
||||||
print_schema,
|
print_schema,
|
||||||
GraphQLArgument,
|
GraphQLArgument,
|
||||||
GraphQLBoolean,
|
GraphQLBoolean,
|
||||||
|
@ -71,118 +70,74 @@ def is_graphene_type(type_):
|
||||||
return True
|
return True
|
||||||
|
|
||||||
|
|
||||||
def resolve_type(resolve_type_func, map_, type_name, root, info, _type):
|
|
||||||
type_ = resolve_type_func(root, info)
|
|
||||||
|
|
||||||
if not type_:
|
|
||||||
return_type = map_[type_name]
|
|
||||||
return default_type_resolver(root, info, return_type)
|
|
||||||
|
|
||||||
if inspect.isclass(type_) and issubclass(type_, ObjectType):
|
|
||||||
graphql_type = map_.get(type_._meta.name)
|
|
||||||
assert graphql_type, "Can't find type {} in schema".format(type_._meta.name)
|
|
||||||
assert graphql_type.graphene_type == type_, (
|
|
||||||
"The type {} does not match with the associated graphene type {}."
|
|
||||||
).format(type_, graphql_type.graphene_type)
|
|
||||||
return graphql_type
|
|
||||||
|
|
||||||
return type_
|
|
||||||
|
|
||||||
|
|
||||||
def is_type_of_from_possible_types(possible_types, root, _info):
|
def is_type_of_from_possible_types(possible_types, root, _info):
|
||||||
return isinstance(root, possible_types)
|
return isinstance(root, possible_types)
|
||||||
|
|
||||||
|
|
||||||
class GrapheneGraphQLSchema(GraphQLSchema):
|
class TypeMap(dict):
|
||||||
"""A GraphQLSchema that can deal with Graphene types as well."""
|
|
||||||
|
|
||||||
def __init__(
|
def __init__(
|
||||||
self,
|
self,
|
||||||
query=None,
|
query=None,
|
||||||
mutation=None,
|
mutation=None,
|
||||||
subscription=None,
|
subscription=None,
|
||||||
types=None,
|
types=None,
|
||||||
directives=None,
|
|
||||||
auto_camelcase=True,
|
auto_camelcase=True,
|
||||||
):
|
):
|
||||||
assert_valid_root_type(query)
|
assert_valid_root_type(query)
|
||||||
assert_valid_root_type(mutation)
|
assert_valid_root_type(mutation)
|
||||||
assert_valid_root_type(subscription)
|
assert_valid_root_type(subscription)
|
||||||
|
if types is None:
|
||||||
|
types = []
|
||||||
|
for type_ in types:
|
||||||
|
assert is_graphene_type(type_)
|
||||||
|
|
||||||
self.auto_camelcase = auto_camelcase
|
self.auto_camelcase = auto_camelcase
|
||||||
super().__init__(query, mutation, subscription, types, directives)
|
|
||||||
|
|
||||||
if query:
|
create_graphql_type = self.add_type
|
||||||
self.query_type = self.get_type(
|
|
||||||
query.name if isinstance(query, GraphQLObjectType) else query._meta.name
|
|
||||||
)
|
|
||||||
if mutation:
|
|
||||||
self.mutation_type = self.get_type(
|
|
||||||
mutation.name
|
|
||||||
if isinstance(mutation, GraphQLObjectType)
|
|
||||||
else mutation._meta.name
|
|
||||||
)
|
|
||||||
if subscription:
|
|
||||||
self.subscription_type = self.get_type(
|
|
||||||
subscription.name
|
|
||||||
if isinstance(subscription, GraphQLObjectType)
|
|
||||||
else subscription._meta.name
|
|
||||||
)
|
|
||||||
|
|
||||||
def get_graphql_type(self, _type):
|
self.query = create_graphql_type(query) if query else None
|
||||||
if not _type:
|
self.mutation = create_graphql_type(mutation) if mutation else None
|
||||||
return _type
|
self.subscription = create_graphql_type(subscription) if subscription else None
|
||||||
if is_type(_type):
|
|
||||||
return _type
|
self.types = [create_graphql_type(graphene_type) for graphene_type in types]
|
||||||
if is_graphene_type(_type):
|
|
||||||
graphql_type = self.get_type(_type._meta.name)
|
def add_type(self, graphene_type):
|
||||||
assert graphql_type, "Type {} not found in this schema.".format(
|
if inspect.isfunction(graphene_type):
|
||||||
_type._meta.name
|
graphene_type = graphene_type()
|
||||||
|
if isinstance(graphene_type, List):
|
||||||
|
return GraphQLList(self.add_type(graphene_type.of_type))
|
||||||
|
if isinstance(graphene_type, NonNull):
|
||||||
|
return GraphQLNonNull(self.add_type(graphene_type.of_type))
|
||||||
|
try:
|
||||||
|
name = graphene_type._meta.name
|
||||||
|
except AttributeError:
|
||||||
|
raise TypeError(
|
||||||
|
"Expected Graphene type, but received: {}.".format(graphene_type)
|
||||||
)
|
)
|
||||||
assert graphql_type.graphene_type == _type
|
graphql_type = self.get(name)
|
||||||
|
if graphql_type:
|
||||||
return graphql_type
|
return graphql_type
|
||||||
raise Exception("{} is not a valid GraphQL type.".format(_type))
|
if issubclass(graphene_type, ObjectType):
|
||||||
|
graphql_type = self.create_objecttype(graphene_type)
|
||||||
# noinspection PyMethodOverriding
|
elif issubclass(graphene_type, InputObjectType):
|
||||||
def type_map_reducer(self, map_, type_):
|
graphql_type = self.create_inputobjecttype(graphene_type)
|
||||||
if not type_:
|
elif issubclass(graphene_type, Interface):
|
||||||
return map_
|
graphql_type = self.create_interface(graphene_type)
|
||||||
if inspect.isfunction(type_):
|
elif issubclass(graphene_type, Scalar):
|
||||||
type_ = type_()
|
graphql_type = self.create_scalar(graphene_type)
|
||||||
if is_graphene_type(type_):
|
elif issubclass(graphene_type, Enum):
|
||||||
return self.graphene_reducer(map_, type_)
|
graphql_type = self.create_enum(graphene_type)
|
||||||
return super().type_map_reducer(map_, type_)
|
elif issubclass(graphene_type, Union):
|
||||||
|
graphql_type = self.construct_union(graphene_type)
|
||||||
def graphene_reducer(self, map_, type_):
|
|
||||||
if isinstance(type_, (List, NonNull)):
|
|
||||||
return self.type_map_reducer(map_, type_.of_type)
|
|
||||||
if type_._meta.name in map_:
|
|
||||||
_type = map_[type_._meta.name]
|
|
||||||
if isinstance(_type, GrapheneGraphQLType):
|
|
||||||
assert _type.graphene_type == type_, (
|
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
|
||||||
).format(_type.graphene_type, type_)
|
|
||||||
return map_
|
|
||||||
|
|
||||||
if issubclass(type_, ObjectType):
|
|
||||||
internal_type = self.construct_objecttype(map_, type_)
|
|
||||||
elif issubclass(type_, InputObjectType):
|
|
||||||
internal_type = self.construct_inputobjecttype(map_, type_)
|
|
||||||
elif issubclass(type_, Interface):
|
|
||||||
internal_type = self.construct_interface(map_, type_)
|
|
||||||
elif issubclass(type_, Scalar):
|
|
||||||
internal_type = self.construct_scalar(type_)
|
|
||||||
elif issubclass(type_, Enum):
|
|
||||||
internal_type = self.construct_enum(type_)
|
|
||||||
elif issubclass(type_, Union):
|
|
||||||
internal_type = self.construct_union(map_, type_)
|
|
||||||
else:
|
else:
|
||||||
raise Exception("Expected Graphene type, but received: {}.".format(type_))
|
raise TypeError(
|
||||||
|
"Expected Graphene type, but received: {}.".format(graphene_type)
|
||||||
return super().type_map_reducer(map_, internal_type)
|
)
|
||||||
|
self[name] = graphql_type
|
||||||
|
return graphql_type
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def construct_scalar(type_):
|
def create_scalar(graphene_type):
|
||||||
# We have a mapping to the original GraphQL types
|
# We have a mapping to the original GraphQL types
|
||||||
# so there are no collisions.
|
# so there are no collisions.
|
||||||
_scalars = {
|
_scalars = {
|
||||||
|
@ -192,29 +147,31 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
Boolean: GraphQLBoolean,
|
Boolean: GraphQLBoolean,
|
||||||
ID: GraphQLID,
|
ID: GraphQLID,
|
||||||
}
|
}
|
||||||
if type_ in _scalars:
|
if graphene_type in _scalars:
|
||||||
return _scalars[type_]
|
return _scalars[graphene_type]
|
||||||
|
|
||||||
return GrapheneScalarType(
|
return GrapheneScalarType(
|
||||||
graphene_type=type_,
|
graphene_type=graphene_type,
|
||||||
name=type_._meta.name,
|
name=graphene_type._meta.name,
|
||||||
description=type_._meta.description,
|
description=graphene_type._meta.description,
|
||||||
serialize=getattr(type_, "serialize", None),
|
serialize=getattr(graphene_type, "serialize", None),
|
||||||
parse_value=getattr(type_, "parse_value", None),
|
parse_value=getattr(graphene_type, "parse_value", None),
|
||||||
parse_literal=getattr(type_, "parse_literal", None),
|
parse_literal=getattr(graphene_type, "parse_literal", None),
|
||||||
)
|
)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def construct_enum(type_):
|
def create_enum(graphene_type):
|
||||||
values = {}
|
values = {}
|
||||||
for name, value in type_._meta.enum.__members__.items():
|
for name, value in graphene_type._meta.enum.__members__.items():
|
||||||
description = getattr(value, "description", None)
|
description = getattr(value, "description", None)
|
||||||
deprecation_reason = getattr(value, "deprecation_reason", None)
|
deprecation_reason = getattr(value, "deprecation_reason", None)
|
||||||
if not description and callable(type_._meta.description):
|
if not description and callable(graphene_type._meta.description):
|
||||||
description = type_._meta.description(value)
|
description = graphene_type._meta.description(value)
|
||||||
|
|
||||||
if not deprecation_reason and callable(type_._meta.deprecation_reason):
|
if not deprecation_reason and callable(
|
||||||
deprecation_reason = type_._meta.deprecation_reason(value)
|
graphene_type._meta.deprecation_reason
|
||||||
|
):
|
||||||
|
deprecation_reason = graphene_type._meta.deprecation_reason(value)
|
||||||
|
|
||||||
values[name] = GraphQLEnumValue(
|
values[name] = GraphQLEnumValue(
|
||||||
value=value.value,
|
value=value.value,
|
||||||
|
@ -223,107 +180,98 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
)
|
)
|
||||||
|
|
||||||
type_description = (
|
type_description = (
|
||||||
type_._meta.description(None)
|
graphene_type._meta.description(None)
|
||||||
if callable(type_._meta.description)
|
if callable(graphene_type._meta.description)
|
||||||
else type_._meta.description
|
else graphene_type._meta.description
|
||||||
)
|
)
|
||||||
|
|
||||||
return GrapheneEnumType(
|
return GrapheneEnumType(
|
||||||
graphene_type=type_,
|
graphene_type=graphene_type,
|
||||||
values=values,
|
values=values,
|
||||||
name=type_._meta.name,
|
name=graphene_type._meta.name,
|
||||||
description=type_description,
|
description=type_description,
|
||||||
)
|
)
|
||||||
|
|
||||||
def construct_objecttype(self, map_, type_):
|
def create_objecttype(self, graphene_type):
|
||||||
if type_._meta.name in map_:
|
create_graphql_type = self.add_type
|
||||||
_type = map_[type_._meta.name]
|
|
||||||
if isinstance(_type, GrapheneGraphQLType):
|
|
||||||
assert _type.graphene_type == type_, (
|
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
|
||||||
).format(_type.graphene_type, type_)
|
|
||||||
return _type
|
|
||||||
|
|
||||||
def interfaces():
|
def interfaces():
|
||||||
interfaces = []
|
interfaces = []
|
||||||
for interface in type_._meta.interfaces:
|
for graphene_interface in graphene_type._meta.interfaces:
|
||||||
self.graphene_reducer(map_, interface)
|
interface = create_graphql_type(graphene_interface)
|
||||||
internal_type = map_[interface._meta.name]
|
assert interface.graphene_type == graphene_interface
|
||||||
assert internal_type.graphene_type == interface
|
interfaces.append(interface)
|
||||||
interfaces.append(internal_type)
|
|
||||||
return interfaces
|
return interfaces
|
||||||
|
|
||||||
if type_._meta.possible_types:
|
if graphene_type._meta.possible_types:
|
||||||
is_type_of = partial(
|
is_type_of = partial(
|
||||||
is_type_of_from_possible_types, type_._meta.possible_types
|
is_type_of_from_possible_types, graphene_type._meta.possible_types
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
is_type_of = type_.is_type_of
|
is_type_of = graphene_type.is_type_of
|
||||||
|
|
||||||
return GrapheneObjectType(
|
return GrapheneObjectType(
|
||||||
graphene_type=type_,
|
graphene_type=graphene_type,
|
||||||
name=type_._meta.name,
|
name=graphene_type._meta.name,
|
||||||
description=type_._meta.description,
|
description=graphene_type._meta.description,
|
||||||
fields=partial(self.construct_fields_for_type, map_, type_),
|
fields=partial(self.create_fields_for_type, graphene_type),
|
||||||
is_type_of=is_type_of,
|
is_type_of=is_type_of,
|
||||||
interfaces=interfaces,
|
interfaces=interfaces,
|
||||||
)
|
)
|
||||||
|
|
||||||
def construct_interface(self, map_, type_):
|
def create_interface(self, graphene_type):
|
||||||
if type_._meta.name in map_:
|
resolve_type = (
|
||||||
_type = map_[type_._meta.name]
|
partial(
|
||||||
if isinstance(_type, GrapheneInterfaceType):
|
self.resolve_type, graphene_type.resolve_type, graphene_type._meta.name
|
||||||
assert _type.graphene_type == type_, (
|
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
|
||||||
).format(_type.graphene_type, type_)
|
|
||||||
return _type
|
|
||||||
|
|
||||||
_resolve_type = None
|
|
||||||
if type_.resolve_type:
|
|
||||||
_resolve_type = partial(
|
|
||||||
resolve_type, type_.resolve_type, map_, type_._meta.name
|
|
||||||
)
|
)
|
||||||
return GrapheneInterfaceType(
|
if graphene_type.resolve_type
|
||||||
graphene_type=type_,
|
else None
|
||||||
name=type_._meta.name,
|
|
||||||
description=type_._meta.description,
|
|
||||||
fields=partial(self.construct_fields_for_type, map_, type_),
|
|
||||||
resolve_type=_resolve_type,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def construct_inputobjecttype(self, map_, type_):
|
return GrapheneInterfaceType(
|
||||||
|
graphene_type=graphene_type,
|
||||||
|
name=graphene_type._meta.name,
|
||||||
|
description=graphene_type._meta.description,
|
||||||
|
fields=partial(self.create_fields_for_type, graphene_type),
|
||||||
|
resolve_type=resolve_type,
|
||||||
|
)
|
||||||
|
|
||||||
|
def create_inputobjecttype(self, graphene_type):
|
||||||
return GrapheneInputObjectType(
|
return GrapheneInputObjectType(
|
||||||
graphene_type=type_,
|
graphene_type=graphene_type,
|
||||||
name=type_._meta.name,
|
name=graphene_type._meta.name,
|
||||||
description=type_._meta.description,
|
description=graphene_type._meta.description,
|
||||||
out_type=type_._meta.container,
|
out_type=graphene_type._meta.container,
|
||||||
fields=partial(
|
fields=partial(
|
||||||
self.construct_fields_for_type, map_, type_, is_input_type=True
|
self.create_fields_for_type, graphene_type, is_input_type=True
|
||||||
),
|
),
|
||||||
)
|
)
|
||||||
|
|
||||||
def construct_union(self, map_, type_):
|
def construct_union(self, graphene_type):
|
||||||
_resolve_type = None
|
create_graphql_type = self.add_type
|
||||||
if type_.resolve_type:
|
|
||||||
_resolve_type = partial(
|
|
||||||
resolve_type, type_.resolve_type, map_, type_._meta.name
|
|
||||||
)
|
|
||||||
|
|
||||||
def types():
|
def types():
|
||||||
union_types = []
|
union_types = []
|
||||||
for objecttype in type_._meta.types:
|
for graphene_objecttype in graphene_type._meta.types:
|
||||||
self.graphene_reducer(map_, objecttype)
|
object_type = create_graphql_type(graphene_objecttype)
|
||||||
internal_type = map_[objecttype._meta.name]
|
assert object_type.graphene_type == graphene_objecttype
|
||||||
assert internal_type.graphene_type == objecttype
|
union_types.append(object_type)
|
||||||
union_types.append(internal_type)
|
|
||||||
return union_types
|
return union_types
|
||||||
|
|
||||||
|
resolve_type = (
|
||||||
|
partial(
|
||||||
|
self.resolve_type, graphene_type.resolve_type, graphene_type._meta.name
|
||||||
|
)
|
||||||
|
if graphene_type.resolve_type
|
||||||
|
else None
|
||||||
|
)
|
||||||
|
|
||||||
return GrapheneUnionType(
|
return GrapheneUnionType(
|
||||||
graphene_type=type_,
|
graphene_type=graphene_type,
|
||||||
name=type_._meta.name,
|
name=graphene_type._meta.name,
|
||||||
description=type_._meta.description,
|
description=graphene_type._meta.description,
|
||||||
types=types,
|
types=types,
|
||||||
resolve_type=_resolve_type,
|
resolve_type=resolve_type,
|
||||||
)
|
)
|
||||||
|
|
||||||
def get_name(self, name):
|
def get_name(self, name):
|
||||||
|
@ -331,15 +279,16 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
return to_camel_case(name)
|
return to_camel_case(name)
|
||||||
return name
|
return name
|
||||||
|
|
||||||
def construct_fields_for_type(self, map_, type_, is_input_type=False):
|
def create_fields_for_type(self, graphene_type, is_input_type=False):
|
||||||
|
create_graphql_type = self.add_type
|
||||||
|
|
||||||
fields = {}
|
fields = {}
|
||||||
for name, field in type_._meta.fields.items():
|
for name, field in graphene_type._meta.fields.items():
|
||||||
if isinstance(field, Dynamic):
|
if isinstance(field, Dynamic):
|
||||||
field = get_field_as(field.get_type(self), _as=Field)
|
field = get_field_as(field.get_type(self), _as=Field)
|
||||||
if not field:
|
if not field:
|
||||||
continue
|
continue
|
||||||
map_ = self.type_map_reducer(map_, field.type)
|
field_type = create_graphql_type(field.type)
|
||||||
field_type = self.get_field_type(map_, field.type)
|
|
||||||
if is_input_type:
|
if is_input_type:
|
||||||
_field = GraphQLInputField(
|
_field = GraphQLInputField(
|
||||||
field_type,
|
field_type,
|
||||||
|
@ -350,8 +299,7 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
else:
|
else:
|
||||||
args = {}
|
args = {}
|
||||||
for arg_name, arg in field.args.items():
|
for arg_name, arg in field.args.items():
|
||||||
map_ = self.type_map_reducer(map_, arg.type)
|
arg_type = create_graphql_type(arg.type)
|
||||||
arg_type = self.get_field_type(map_, arg.type)
|
|
||||||
processed_arg_name = arg.name or self.get_name(arg_name)
|
processed_arg_name = arg.name or self.get_name(arg_name)
|
||||||
args[processed_arg_name] = GraphQLArgument(
|
args[processed_arg_name] = GraphQLArgument(
|
||||||
arg_type,
|
arg_type,
|
||||||
|
@ -361,12 +309,13 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
if isinstance(arg.type, NonNull)
|
if isinstance(arg.type, NonNull)
|
||||||
else arg.default_value,
|
else arg.default_value,
|
||||||
)
|
)
|
||||||
|
resolve = field.get_resolver(
|
||||||
|
self.get_resolver(graphene_type, name, field.default_value)
|
||||||
|
)
|
||||||
_field = GraphQLField(
|
_field = GraphQLField(
|
||||||
field_type,
|
field_type,
|
||||||
args=args,
|
args=args,
|
||||||
resolve=field.get_resolver(
|
resolve=resolve,
|
||||||
self.get_resolver_for_type(type_, name, field.default_value)
|
|
||||||
),
|
|
||||||
deprecation_reason=field.deprecation_reason,
|
deprecation_reason=field.deprecation_reason,
|
||||||
description=field.description,
|
description=field.description,
|
||||||
)
|
)
|
||||||
|
@ -374,15 +323,32 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
fields[field_name] = _field
|
fields[field_name] = _field
|
||||||
return fields
|
return fields
|
||||||
|
|
||||||
def get_resolver_for_type(self, type_, name, default_value):
|
def resolve_type(self, resolve_type_func, type_name, root, info, _type):
|
||||||
if not issubclass(type_, ObjectType):
|
type_ = resolve_type_func(root, info)
|
||||||
|
|
||||||
|
if not type_:
|
||||||
|
return_type = self[type_name]
|
||||||
|
return default_type_resolver(root, info, return_type)
|
||||||
|
|
||||||
|
if inspect.isclass(type_) and issubclass(type_, ObjectType):
|
||||||
|
graphql_type = self.get(type_._meta.name)
|
||||||
|
assert graphql_type, "Can't find type {} in schema".format(type_._meta.name)
|
||||||
|
assert graphql_type.graphene_type == type_, (
|
||||||
|
"The type {} does not match with the associated graphene type {}."
|
||||||
|
).format(type_, graphql_type.graphene_type)
|
||||||
|
return graphql_type
|
||||||
|
|
||||||
|
return type_
|
||||||
|
|
||||||
|
def get_resolver(self, graphene_type, name, default_value):
|
||||||
|
if not issubclass(graphene_type, ObjectType):
|
||||||
return
|
return
|
||||||
resolver = getattr(type_, "resolve_{}".format(name), None)
|
resolver = getattr(graphene_type, "resolve_{}".format(name), None)
|
||||||
if not resolver:
|
if not resolver:
|
||||||
# If we don't find the resolver in the ObjectType class, then try to
|
# If we don't find the resolver in the ObjectType class, then try to
|
||||||
# find it in each of the interfaces
|
# find it in each of the interfaces
|
||||||
interface_resolver = None
|
interface_resolver = None
|
||||||
for interface in type_._meta.interfaces:
|
for interface in graphene_type._meta.interfaces:
|
||||||
if name not in interface._meta.fields:
|
if name not in interface._meta.fields:
|
||||||
continue
|
continue
|
||||||
interface_resolver = getattr(interface, "resolve_{}".format(name), None)
|
interface_resolver = getattr(interface, "resolve_{}".format(name), None)
|
||||||
|
@ -394,16 +360,11 @@ class GrapheneGraphQLSchema(GraphQLSchema):
|
||||||
if resolver:
|
if resolver:
|
||||||
return get_unbound_function(resolver)
|
return get_unbound_function(resolver)
|
||||||
|
|
||||||
default_resolver = type_._meta.default_resolver or get_default_resolver()
|
default_resolver = (
|
||||||
|
graphene_type._meta.default_resolver or get_default_resolver()
|
||||||
|
)
|
||||||
return partial(default_resolver, name, default_value)
|
return partial(default_resolver, name, default_value)
|
||||||
|
|
||||||
def get_field_type(self, map_, type_):
|
|
||||||
if isinstance(type_, List):
|
|
||||||
return GraphQLList(self.get_field_type(map_, type_.of_type))
|
|
||||||
if isinstance(type_, NonNull):
|
|
||||||
return GraphQLNonNull(self.get_field_type(map_, type_.of_type))
|
|
||||||
return map_.get(type_._meta.name)
|
|
||||||
|
|
||||||
|
|
||||||
class Schema:
|
class Schema:
|
||||||
"""Schema Definition.
|
"""Schema Definition.
|
||||||
|
@ -419,11 +380,11 @@ class Schema:
|
||||||
fields to *create, update or delete* data in your API.
|
fields to *create, update or delete* data in your API.
|
||||||
subscription (ObjectType, optional): Root subscription *ObjectType*. Describes entry point
|
subscription (ObjectType, optional): Root subscription *ObjectType*. Describes entry point
|
||||||
for fields to receive continuous updates.
|
for fields to receive continuous updates.
|
||||||
|
types (List[ObjectType], optional): List of any types to include in schema that
|
||||||
|
may not be introspected through root types.
|
||||||
directives (List[GraphQLDirective], optional): List of custom directives to include in the
|
directives (List[GraphQLDirective], optional): List of custom directives to include in the
|
||||||
GraphQL schema. Defaults to only include directives defined by GraphQL spec (@include
|
GraphQL schema. Defaults to only include directives defined by GraphQL spec (@include
|
||||||
and @skip) [GraphQLIncludeDirective, GraphQLSkipDirective].
|
and @skip) [GraphQLIncludeDirective, GraphQLSkipDirective].
|
||||||
types (List[GraphQLType], optional): List of any types to include in schema that
|
|
||||||
may not be introspected through root types.
|
|
||||||
auto_camelcase (bool): Fieldnames will be transformed in Schema's TypeMap from snake_case
|
auto_camelcase (bool): Fieldnames will be transformed in Schema's TypeMap from snake_case
|
||||||
to camelCase (preferred by GraphQL standard). Default True.
|
to camelCase (preferred by GraphQL standard). Default True.
|
||||||
"""
|
"""
|
||||||
|
@ -440,13 +401,15 @@ class Schema:
|
||||||
self.query = query
|
self.query = query
|
||||||
self.mutation = mutation
|
self.mutation = mutation
|
||||||
self.subscription = subscription
|
self.subscription = subscription
|
||||||
self.graphql_schema = GrapheneGraphQLSchema(
|
type_map = TypeMap(
|
||||||
query,
|
query, mutation, subscription, types, auto_camelcase=auto_camelcase
|
||||||
mutation,
|
)
|
||||||
subscription,
|
self.graphql_schema = GraphQLSchema(
|
||||||
types,
|
type_map.query,
|
||||||
|
type_map.mutation,
|
||||||
|
type_map.subscription,
|
||||||
|
type_map.types,
|
||||||
directives,
|
directives,
|
||||||
auto_camelcase=auto_camelcase,
|
|
||||||
)
|
)
|
||||||
|
|
||||||
def __str__(self):
|
def __str__(self):
|
||||||
|
|
|
@ -3,7 +3,7 @@ import datetime
|
||||||
import pytz
|
import pytz
|
||||||
from graphql import GraphQLError
|
from graphql import GraphQLError
|
||||||
|
|
||||||
from pytest import fixture, mark
|
from pytest import fixture
|
||||||
|
|
||||||
from ..datetime import Date, DateTime, Time
|
from ..datetime import Date, DateTime, Time
|
||||||
from ..objecttype import ObjectType
|
from ..objecttype import ObjectType
|
||||||
|
@ -84,8 +84,9 @@ def test_bad_datetime_query():
|
||||||
assert result.errors and len(result.errors) == 1
|
assert result.errors and len(result.errors) == 1
|
||||||
error = result.errors[0]
|
error = result.errors[0]
|
||||||
assert isinstance(error, GraphQLError)
|
assert isinstance(error, GraphQLError)
|
||||||
assert error.message == (
|
assert (
|
||||||
'Expected type DateTime, found "Some string that\'s not a datetime".'
|
error.message == "DateTime cannot represent value:"
|
||||||
|
' "Some string that\'s not a datetime"'
|
||||||
)
|
)
|
||||||
assert result.data is None
|
assert result.data is None
|
||||||
|
|
||||||
|
@ -97,8 +98,9 @@ def test_bad_date_query():
|
||||||
|
|
||||||
error = result.errors[0]
|
error = result.errors[0]
|
||||||
assert isinstance(error, GraphQLError)
|
assert isinstance(error, GraphQLError)
|
||||||
assert error.message == (
|
assert (
|
||||||
'Expected type Date, found "Some string that\'s not a date".'
|
error.message == "Date cannot represent value:"
|
||||||
|
' "Some string that\'s not a date"'
|
||||||
)
|
)
|
||||||
assert result.data is None
|
assert result.data is None
|
||||||
|
|
||||||
|
@ -110,8 +112,9 @@ def test_bad_time_query():
|
||||||
|
|
||||||
error = result.errors[0]
|
error = result.errors[0]
|
||||||
assert isinstance(error, GraphQLError)
|
assert isinstance(error, GraphQLError)
|
||||||
assert error.message == (
|
assert (
|
||||||
'Expected type Time, found "Some string that\'s not a time".'
|
error.message == "Time cannot represent value:"
|
||||||
|
' "Some string that\'s not a time"'
|
||||||
)
|
)
|
||||||
assert result.data is None
|
assert result.data is None
|
||||||
|
|
||||||
|
@ -174,9 +177,6 @@ def test_time_query_variable(sample_time):
|
||||||
assert result.data == {"time": isoformat}
|
assert result.data == {"time": isoformat}
|
||||||
|
|
||||||
|
|
||||||
@mark.xfail(
|
|
||||||
reason="creating the error message fails when un-parsable object is not JSON serializable."
|
|
||||||
)
|
|
||||||
def test_bad_variables(sample_date, sample_datetime, sample_time):
|
def test_bad_variables(sample_date, sample_datetime, sample_time):
|
||||||
def _test_bad_variables(type_, input_):
|
def _test_bad_variables(type_, input_):
|
||||||
result = schema.execute(
|
result = schema.execute(
|
||||||
|
@ -185,8 +185,6 @@ def test_bad_variables(sample_date, sample_datetime, sample_time):
|
||||||
),
|
),
|
||||||
variables={"input": input_},
|
variables={"input": input_},
|
||||||
)
|
)
|
||||||
# when `input` is not JSON serializable formatting the error message in
|
|
||||||
# `graphql.utils.is_valid_value` line 79 fails with a TypeError
|
|
||||||
assert isinstance(result.errors, list)
|
assert isinstance(result.errors, list)
|
||||||
assert len(result.errors) == 1
|
assert len(result.errors) == 1
|
||||||
assert isinstance(result.errors[0], GraphQLError)
|
assert isinstance(result.errors[0], GraphQLError)
|
||||||
|
@ -205,7 +203,6 @@ def test_bad_variables(sample_date, sample_datetime, sample_time):
|
||||||
("DateTime", time),
|
("DateTime", time),
|
||||||
("Date", not_a_date),
|
("Date", not_a_date),
|
||||||
("Date", not_a_date_str),
|
("Date", not_a_date_str),
|
||||||
("Date", now),
|
|
||||||
("Date", time),
|
("Date", time),
|
||||||
("Time", not_a_date),
|
("Time", not_a_date),
|
||||||
("Time", not_a_date_str),
|
("Time", not_a_date_str),
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
from pytest import raises
|
from pytest import raises
|
||||||
|
|
||||||
|
from graphql.type import GraphQLObjectType, GraphQLSchema
|
||||||
from graphql.pyutils import dedent
|
from graphql.pyutils import dedent
|
||||||
|
|
||||||
from ..field import Field
|
from ..field import Field
|
||||||
|
@ -17,8 +18,13 @@ class Query(ObjectType):
|
||||||
|
|
||||||
|
|
||||||
def test_schema():
|
def test_schema():
|
||||||
schema = Schema(Query).graphql_schema
|
schema = Schema(Query)
|
||||||
assert schema.query_type == schema.get_graphql_type(Query)
|
graphql_schema = schema.graphql_schema
|
||||||
|
assert isinstance(graphql_schema, GraphQLSchema)
|
||||||
|
query_type = graphql_schema.query_type
|
||||||
|
assert isinstance(query_type, GraphQLObjectType)
|
||||||
|
assert query_type.name == "Query"
|
||||||
|
assert query_type.graphene_type is Query
|
||||||
|
|
||||||
|
|
||||||
def test_schema_get_type():
|
def test_schema_get_type():
|
||||||
|
@ -39,13 +45,13 @@ def test_schema_str():
|
||||||
schema = Schema(Query)
|
schema = Schema(Query)
|
||||||
assert str(schema) == dedent(
|
assert str(schema) == dedent(
|
||||||
"""
|
"""
|
||||||
type MyOtherType {
|
|
||||||
field: String
|
|
||||||
}
|
|
||||||
|
|
||||||
type Query {
|
type Query {
|
||||||
inner: MyOtherType
|
inner: MyOtherType
|
||||||
}
|
}
|
||||||
|
|
||||||
|
type MyOtherType {
|
||||||
|
field: String
|
||||||
|
}
|
||||||
"""
|
"""
|
||||||
)
|
)
|
||||||
|
|
||||||
|
|
|
@ -1,5 +1,3 @@
|
||||||
from pytest import raises
|
|
||||||
|
|
||||||
from graphql.type import (
|
from graphql.type import (
|
||||||
GraphQLArgument,
|
GraphQLArgument,
|
||||||
GraphQLEnumType,
|
GraphQLEnumType,
|
||||||
|
@ -21,13 +19,13 @@ from ..interface import Interface
|
||||||
from ..objecttype import ObjectType
|
from ..objecttype import ObjectType
|
||||||
from ..scalars import Int, String
|
from ..scalars import Int, String
|
||||||
from ..structures import List, NonNull
|
from ..structures import List, NonNull
|
||||||
from ..schema import GrapheneGraphQLSchema, resolve_type
|
from ..schema import Schema
|
||||||
|
|
||||||
|
|
||||||
def create_type_map(types, auto_camelcase=True):
|
def create_type_map(types, auto_camelcase=True):
|
||||||
query = GraphQLObjectType("Query", {})
|
query = type("Query", (ObjectType,), {})
|
||||||
schema = GrapheneGraphQLSchema(query, types=types, auto_camelcase=auto_camelcase)
|
schema = Schema(query, types=types, auto_camelcase=auto_camelcase)
|
||||||
return schema.type_map
|
return schema.graphql_schema.type_map
|
||||||
|
|
||||||
|
|
||||||
def test_enum():
|
def test_enum():
|
||||||
|
@ -272,20 +270,3 @@ def test_objecttype_with_possible_types():
|
||||||
assert graphql_type.is_type_of
|
assert graphql_type.is_type_of
|
||||||
assert graphql_type.is_type_of({}, None) is True
|
assert graphql_type.is_type_of({}, None) is True
|
||||||
assert graphql_type.is_type_of(MyObjectType(), None) is False
|
assert graphql_type.is_type_of(MyObjectType(), None) is False
|
||||||
|
|
||||||
|
|
||||||
def test_resolve_type_with_missing_type():
|
|
||||||
class MyObjectType(ObjectType):
|
|
||||||
foo_bar = String()
|
|
||||||
|
|
||||||
class MyOtherObjectType(ObjectType):
|
|
||||||
fizz_buzz = String()
|
|
||||||
|
|
||||||
def resolve_type_func(root, info):
|
|
||||||
return MyOtherObjectType
|
|
||||||
|
|
||||||
type_map = create_type_map([MyObjectType])
|
|
||||||
with raises(AssertionError) as excinfo:
|
|
||||||
resolve_type(resolve_type_func, type_map, "MyOtherObjectType", {}, {}, None)
|
|
||||||
|
|
||||||
assert "MyOtherObjectTyp" in str(excinfo.value)
|
|
||||||
|
|
2
setup.py
2
setup.py
|
@ -82,7 +82,7 @@ setup(
|
||||||
keywords="api graphql protocol rest relay graphene",
|
keywords="api graphql protocol rest relay graphene",
|
||||||
packages=find_packages(exclude=["tests", "tests.*", "examples"]),
|
packages=find_packages(exclude=["tests", "tests.*", "examples"]),
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"graphql-core>=3.0.3,<3.1",
|
"graphql-core>=3.1.0b1,<4",
|
||||||
"graphql-relay>=3.0,<4",
|
"graphql-relay>=3.0,<4",
|
||||||
"aniso8601>=8,<9",
|
"aniso8601>=8,<9",
|
||||||
"unidecode>=1.1.1,<2",
|
"unidecode>=1.1.1,<2",
|
||||||
|
|
Loading…
Reference in New Issue
Block a user