mirror of
https://github.com/graphql-python/graphene.git
synced 2025-09-21 19:32:33 +03:00
Start porting to graphql-core-next
This commit is contained in:
parent
abff3d75a3
commit
8a7a321136
7
Makefile
7
Makefile
|
@ -9,3 +9,10 @@ docs:
|
||||||
pip install -r requirements.txt &&\
|
pip install -r requirements.txt &&\
|
||||||
make html &&\
|
make html &&\
|
||||||
cd -
|
cd -
|
||||||
|
|
||||||
|
|
||||||
|
dev-setup:
|
||||||
|
pip install -e ".[test]"
|
||||||
|
|
||||||
|
tests:
|
||||||
|
py.test graphene
|
|
@ -28,7 +28,7 @@ from .types import (
|
||||||
Dynamic,
|
Dynamic,
|
||||||
Union,
|
Union,
|
||||||
Context,
|
Context,
|
||||||
ResolveInfo,
|
GraphQLResolveInfo,
|
||||||
)
|
)
|
||||||
from .relay import (
|
from .relay import (
|
||||||
Node,
|
Node,
|
||||||
|
@ -84,7 +84,7 @@ __all__ = [
|
||||||
"PageInfo",
|
"PageInfo",
|
||||||
"lazy_import",
|
"lazy_import",
|
||||||
"Context",
|
"Context",
|
||||||
"ResolveInfo",
|
"GraphQLResolveInfo",
|
||||||
# Deprecated
|
# Deprecated
|
||||||
"AbstractType",
|
"AbstractType",
|
||||||
]
|
]
|
||||||
|
|
|
@ -2,8 +2,6 @@ from __future__ import absolute_import
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from graphql.pyutils.compat import Enum
|
|
||||||
|
|
||||||
try:
|
try:
|
||||||
from inspect import signature
|
from inspect import signature
|
||||||
except ImportError:
|
except ImportError:
|
||||||
|
|
|
@ -2,14 +2,155 @@ import re
|
||||||
from collections import Iterable, OrderedDict
|
from collections import Iterable, OrderedDict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from graphql_relay import connection_from_list
|
|
||||||
|
|
||||||
from ..types import Boolean, Enum, Int, Interface, List, NonNull, Scalar, String, Union
|
from ..types import Boolean, Enum, Int, Interface, List, NonNull, Scalar, String, Union
|
||||||
from ..types.field import Field
|
from ..types.field import Field
|
||||||
from ..types.objecttype import ObjectType, ObjectTypeOptions
|
from ..types.objecttype import ObjectType, ObjectTypeOptions
|
||||||
from ..utils.thenables import maybe_thenable
|
from ..utils.thenables import maybe_thenable
|
||||||
|
from ..utils import base64, is_str, unbase64
|
||||||
from .node import is_node
|
from .node import is_node
|
||||||
|
|
||||||
|
from .connectiontypes import ConnectionType, PageInfoType, EdgeType
|
||||||
|
|
||||||
|
|
||||||
|
def connection_from_list(data, args=None, **kwargs):
|
||||||
|
'''
|
||||||
|
A simple function that accepts an array and connection arguments, and returns
|
||||||
|
a connection object for use in GraphQL. It uses array offsets as pagination,
|
||||||
|
so pagination will only work if the array is static.
|
||||||
|
'''
|
||||||
|
_len = len(data)
|
||||||
|
return connection_from_list_slice(
|
||||||
|
data,
|
||||||
|
args,
|
||||||
|
slice_start=0,
|
||||||
|
list_length=_len,
|
||||||
|
list_slice_length=_len,
|
||||||
|
**kwargs
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def connection_from_list_slice(list_slice, args=None, connection_type=None,
|
||||||
|
edge_type=None, pageinfo_type=None,
|
||||||
|
slice_start=0, list_length=0, list_slice_length=None):
|
||||||
|
'''
|
||||||
|
Given a slice (subset) of an array, returns a connection object for use in
|
||||||
|
GraphQL.
|
||||||
|
This function is similar to `connectionFromArray`, but is intended for use
|
||||||
|
cases where you know the cardinality of the connection, consider it too large
|
||||||
|
to materialize the entire array, and instead wish pass in a slice of the
|
||||||
|
total result large enough to cover the range specified in `args`.
|
||||||
|
'''
|
||||||
|
connection_type = connection_type or Connection
|
||||||
|
edge_type = edge_type or Edge
|
||||||
|
pageinfo_type = pageinfo_type or PageInfo
|
||||||
|
|
||||||
|
args = args or {}
|
||||||
|
|
||||||
|
before = args.get('before')
|
||||||
|
after = args.get('after')
|
||||||
|
first = args.get('first')
|
||||||
|
last = args.get('last')
|
||||||
|
if list_slice_length is None:
|
||||||
|
list_slice_length = len(list_slice)
|
||||||
|
slice_end = slice_start + list_slice_length
|
||||||
|
before_offset = get_offset_with_default(before, list_length)
|
||||||
|
after_offset = get_offset_with_default(after, -1)
|
||||||
|
|
||||||
|
start_offset = max(
|
||||||
|
slice_start - 1,
|
||||||
|
after_offset,
|
||||||
|
-1
|
||||||
|
) + 1
|
||||||
|
end_offset = min(
|
||||||
|
slice_end,
|
||||||
|
before_offset,
|
||||||
|
list_length
|
||||||
|
)
|
||||||
|
if isinstance(first, int):
|
||||||
|
end_offset = min(
|
||||||
|
end_offset,
|
||||||
|
start_offset + first
|
||||||
|
)
|
||||||
|
if isinstance(last, int):
|
||||||
|
start_offset = max(
|
||||||
|
start_offset,
|
||||||
|
end_offset - last
|
||||||
|
)
|
||||||
|
|
||||||
|
# If supplied slice is too large, trim it down before mapping over it.
|
||||||
|
_slice = list_slice[
|
||||||
|
max(start_offset - slice_start, 0):
|
||||||
|
list_slice_length - (slice_end - end_offset)
|
||||||
|
]
|
||||||
|
edges = [
|
||||||
|
edge_type(
|
||||||
|
node=node,
|
||||||
|
cursor=offset_to_cursor(start_offset + i)
|
||||||
|
)
|
||||||
|
for i, node in enumerate(_slice)
|
||||||
|
]
|
||||||
|
|
||||||
|
|
||||||
|
first_edge_cursor = edges[0].cursor if edges else None
|
||||||
|
last_edge_cursor = edges[-1].cursor if edges else None
|
||||||
|
lower_bound = after_offset + 1 if after else 0
|
||||||
|
upper_bound = before_offset if before else list_length
|
||||||
|
|
||||||
|
return connection_type(
|
||||||
|
edges=edges,
|
||||||
|
page_info=pageinfo_type(
|
||||||
|
start_cursor=first_edge_cursor,
|
||||||
|
end_cursor=last_edge_cursor,
|
||||||
|
has_previous_page=isinstance(last, int) and start_offset > lower_bound,
|
||||||
|
has_next_page=isinstance(first, int) and end_offset < upper_bound
|
||||||
|
)
|
||||||
|
)
|
||||||
|
|
||||||
|
|
||||||
|
def offset_to_cursor(offset):
|
||||||
|
'''
|
||||||
|
Creates the cursor string from an offset.
|
||||||
|
'''
|
||||||
|
return base64(PREFIX + str(offset))
|
||||||
|
|
||||||
|
|
||||||
|
def cursor_to_offset(cursor):
|
||||||
|
'''
|
||||||
|
Rederives the offset from the cursor string.
|
||||||
|
'''
|
||||||
|
try:
|
||||||
|
return int(unbase64(cursor)[len(PREFIX):])
|
||||||
|
except:
|
||||||
|
return None
|
||||||
|
|
||||||
|
|
||||||
|
def cursor_for_object_in_connection(data, _object):
|
||||||
|
'''
|
||||||
|
Return the cursor associated with an object in an array.
|
||||||
|
'''
|
||||||
|
if _object not in data:
|
||||||
|
return None
|
||||||
|
|
||||||
|
offset = data.index(_object)
|
||||||
|
return offset_to_cursor(offset)
|
||||||
|
|
||||||
|
|
||||||
|
def get_offset_with_default(cursor=None, default_offset=0):
|
||||||
|
'''
|
||||||
|
Given an optional cursor and a default offset, returns the offset
|
||||||
|
to use; if the cursor contains a valid offset, that will be used,
|
||||||
|
otherwise it will be the default.
|
||||||
|
'''
|
||||||
|
if not is_str(cursor):
|
||||||
|
return default_offset
|
||||||
|
|
||||||
|
offset = cursor_to_offset(cursor)
|
||||||
|
try:
|
||||||
|
return int(offset)
|
||||||
|
except:
|
||||||
|
return default_offset
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
class PageInfo(ObjectType):
|
class PageInfo(ObjectType):
|
||||||
class Meta:
|
class Meta:
|
||||||
|
|
42
graphene/relay/connectiontypes.py
Normal file
42
graphene/relay/connectiontypes.py
Normal file
|
@ -0,0 +1,42 @@
|
||||||
|
class ConnectionType:
|
||||||
|
|
||||||
|
def __init__(self, edges, page_info):
|
||||||
|
self.edges = edges
|
||||||
|
self.page_info = page_info
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
'edges': [e.to_dict() for e in self.edges],
|
||||||
|
'pageInfo': self.page_info.to_dict(),
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class PageInfoType:
|
||||||
|
|
||||||
|
def __init__(self, start_cursor="", end_cursor="",
|
||||||
|
has_previous_page=False, has_next_page=False):
|
||||||
|
self.startCursor = start_cursor
|
||||||
|
self.endCursor = end_cursor
|
||||||
|
self.hasPreviousPage = has_previous_page
|
||||||
|
self.hasNextPage = has_next_page
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
'startCursor': self.startCursor,
|
||||||
|
'endCursor': self.endCursor,
|
||||||
|
'hasPreviousPage': self.hasPreviousPage,
|
||||||
|
'hasNextPage': self.hasNextPage,
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
class EdgeType:
|
||||||
|
|
||||||
|
def __init__(self, node, cursor):
|
||||||
|
self.node = node
|
||||||
|
self.cursor = cursor
|
||||||
|
|
||||||
|
def to_dict(self):
|
||||||
|
return {
|
||||||
|
'node': self.node,
|
||||||
|
'cursor': self.cursor,
|
||||||
|
}
|
|
@ -2,12 +2,12 @@ from collections import OrderedDict
|
||||||
from functools import partial
|
from functools import partial
|
||||||
from inspect import isclass
|
from inspect import isclass
|
||||||
|
|
||||||
from graphql_relay import from_global_id, to_global_id
|
|
||||||
|
|
||||||
from ..types import ID, Field, Interface, ObjectType
|
from ..types import ID, Field, Interface, ObjectType
|
||||||
from ..types.interface import InterfaceOptions
|
from ..types.interface import InterfaceOptions
|
||||||
from ..types.utils import get_type
|
from ..types.utils import get_type
|
||||||
|
|
||||||
|
from .utils import base64, unbase64
|
||||||
|
|
||||||
|
|
||||||
def is_node(objecttype):
|
def is_node(objecttype):
|
||||||
"""
|
"""
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from graphql_relay.utils import base64
|
from ..utils import base64
|
||||||
from promise import Promise
|
from promise import Promise
|
||||||
|
|
||||||
from ...types import ObjectType, Schema, String
|
from ...types import ObjectType, Schema, String
|
||||||
|
|
|
@ -1,4 +1,4 @@
|
||||||
from graphql_relay import to_global_id
|
from ..utils import to_global_id
|
||||||
|
|
||||||
from ...types import ID, NonNull, ObjectType, String
|
from ...types import ID, NonNull, ObjectType, String
|
||||||
from ...types.definitions import GrapheneObjectType
|
from ...types.definitions import GrapheneObjectType
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
from graphql_relay import to_global_id
|
from ..utils import to_global_id
|
||||||
|
|
||||||
from ...types import ObjectType, Schema, String
|
from ...types import ObjectType, Schema, String
|
||||||
from ..node import Node, is_node
|
from ..node import Node, is_node
|
||||||
|
|
19
graphene/relay/utils.py
Normal file
19
graphene/relay/utils.py
Normal file
|
@ -0,0 +1,19 @@
|
||||||
|
from ..utils import base64, unbase64
|
||||||
|
|
||||||
|
|
||||||
|
def to_global_id(type, id):
|
||||||
|
'''
|
||||||
|
Takes a type name and an ID specific to that type name, and returns a
|
||||||
|
"global ID" that is unique among all types.
|
||||||
|
'''
|
||||||
|
return base64(':'.join([type, text_type(id)]))
|
||||||
|
|
||||||
|
|
||||||
|
def from_global_id(global_id):
|
||||||
|
'''
|
||||||
|
Takes the "global ID" created by toGlobalID, and retuns the type name and ID
|
||||||
|
used to create it.
|
||||||
|
'''
|
||||||
|
unbased_global_id = unbase64(global_id)
|
||||||
|
_type, _id = unbased_global_id.split(':', 1)
|
||||||
|
return _type, _id
|
|
@ -1,5 +1,5 @@
|
||||||
# flake8: noqa
|
# flake8: noqa
|
||||||
from graphql import ResolveInfo
|
from graphql import GraphQLResolveInfo
|
||||||
|
|
||||||
from .objecttype import ObjectType
|
from .objecttype import ObjectType
|
||||||
from .interface import Interface
|
from .interface import Interface
|
||||||
|
@ -51,7 +51,7 @@ __all__ = [
|
||||||
"Dynamic",
|
"Dynamic",
|
||||||
"Union",
|
"Union",
|
||||||
"Context",
|
"Context",
|
||||||
"ResolveInfo",
|
"GraphQLResolveInfo",
|
||||||
# Deprecated
|
# Deprecated
|
||||||
"AbstractType",
|
"AbstractType",
|
||||||
]
|
]
|
||||||
|
|
|
@ -1,10 +1,11 @@
|
||||||
from collections import OrderedDict
|
from collections import OrderedDict
|
||||||
|
|
||||||
|
from enum import Enum
|
||||||
|
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from graphene.utils.subclass_with_meta import SubclassWithMeta_Meta
|
from graphene.utils.subclass_with_meta import SubclassWithMeta_Meta
|
||||||
|
|
||||||
from ..pyutils.compat import Enum as PyEnum
|
|
||||||
from .base import BaseOptions, BaseType
|
from .base import BaseOptions, BaseType
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
|
||||||
|
@ -15,8 +16,6 @@ def eq_enum(self, other):
|
||||||
return self.value is other
|
return self.value is other
|
||||||
|
|
||||||
|
|
||||||
EnumType = type(PyEnum)
|
|
||||||
|
|
||||||
|
|
||||||
class EnumOptions(BaseOptions):
|
class EnumOptions(BaseOptions):
|
||||||
enum = None # type: Enum
|
enum = None # type: Enum
|
||||||
|
@ -29,7 +28,7 @@ class EnumMeta(SubclassWithMeta_Meta):
|
||||||
# We remove the Meta attribute from the class to not collide
|
# We remove the Meta attribute from the class to not collide
|
||||||
# with the enum values.
|
# with the enum values.
|
||||||
enum_members.pop("Meta", None)
|
enum_members.pop("Meta", None)
|
||||||
enum = PyEnum(cls.__name__, enum_members)
|
enum = Enum(cls.__name__, enum_members)
|
||||||
return SubclassWithMeta_Meta.__new__(
|
return SubclassWithMeta_Meta.__new__(
|
||||||
cls, name, bases, OrderedDict(classdict, __enum__=enum), **options
|
cls, name, bases, OrderedDict(classdict, __enum__=enum), **options
|
||||||
)
|
)
|
||||||
|
@ -46,7 +45,8 @@ class EnumMeta(SubclassWithMeta_Meta):
|
||||||
def __call__(cls, *args, **kwargs): # noqa: N805
|
def __call__(cls, *args, **kwargs): # noqa: N805
|
||||||
if cls is Enum:
|
if cls is Enum:
|
||||||
description = kwargs.pop("description", None)
|
description = kwargs.pop("description", None)
|
||||||
return cls.from_enum(PyEnum(*args, **kwargs), description=description)
|
kwargs['description'] = description
|
||||||
|
return Enum(*args, **kwargs)
|
||||||
return super(EnumMeta, cls).__call__(*args, **kwargs)
|
return super(EnumMeta, cls).__call__(*args, **kwargs)
|
||||||
# return cls._meta.enum(*args, **kwargs)
|
# return cls._meta.enum(*args, **kwargs)
|
||||||
|
|
||||||
|
|
|
@ -1,12 +1,12 @@
|
||||||
from __future__ import unicode_literals
|
from __future__ import unicode_literals
|
||||||
|
|
||||||
from graphql.language.ast import (
|
from graphql.language.ast import (
|
||||||
BooleanValue,
|
BooleanValueNode,
|
||||||
FloatValue,
|
FloatValueNode,
|
||||||
IntValue,
|
IntValueNode,
|
||||||
ListValue,
|
ListValueNode,
|
||||||
ObjectValue,
|
ObjectValueNode,
|
||||||
StringValue,
|
StringValueNode,
|
||||||
)
|
)
|
||||||
|
|
||||||
from graphene.types.scalars import MAX_INT, MIN_INT
|
from graphene.types.scalars import MAX_INT, MIN_INT
|
||||||
|
@ -30,15 +30,15 @@ class GenericScalar(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_literal(ast):
|
def parse_literal(ast):
|
||||||
if isinstance(ast, (StringValue, BooleanValue)):
|
if isinstance(ast, (StringValueNode, BooleanValueNode)):
|
||||||
return ast.value
|
return ast.value
|
||||||
elif isinstance(ast, IntValue):
|
elif isinstance(ast, IntValueNode):
|
||||||
num = int(ast.value)
|
num = int(ast.value)
|
||||||
if MIN_INT <= num <= MAX_INT:
|
if MIN_INT <= num <= MAX_INT:
|
||||||
return num
|
return num
|
||||||
elif isinstance(ast, FloatValue):
|
elif isinstance(ast, FloatValueNode):
|
||||||
return float(ast.value)
|
return float(ast.value)
|
||||||
elif isinstance(ast, ListValue):
|
elif isinstance(ast, ListValueNode):
|
||||||
return [GenericScalar.parse_literal(value) for value in ast.values]
|
return [GenericScalar.parse_literal(value) for value in ast.values]
|
||||||
elif isinstance(ast, ObjectValue):
|
elif isinstance(ast, ObjectValue):
|
||||||
return {
|
return {
|
||||||
|
|
|
@ -1,5 +1,10 @@
|
||||||
import six
|
import six
|
||||||
from graphql.language.ast import BooleanValue, FloatValue, IntValue, StringValue
|
from graphql.language.ast import (
|
||||||
|
BooleanValueNode,
|
||||||
|
FloatValueNode,
|
||||||
|
IntValueNode,
|
||||||
|
StringValueNode
|
||||||
|
)
|
||||||
|
|
||||||
from .base import BaseOptions, BaseType
|
from .base import BaseOptions, BaseType
|
||||||
from .unmountedtype import UnmountedType
|
from .unmountedtype import UnmountedType
|
||||||
|
@ -99,7 +104,7 @@ class Float(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_literal(ast):
|
def parse_literal(ast):
|
||||||
if isinstance(ast, (FloatValue, IntValue)):
|
if isinstance(ast, (FloatValueNode, IntValueNode)):
|
||||||
return float(ast.value)
|
return float(ast.value)
|
||||||
|
|
||||||
|
|
||||||
|
@ -121,7 +126,7 @@ class String(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_literal(ast):
|
def parse_literal(ast):
|
||||||
if isinstance(ast, StringValue):
|
if isinstance(ast, StringValueNode):
|
||||||
return ast.value
|
return ast.value
|
||||||
|
|
||||||
|
|
||||||
|
@ -135,7 +140,7 @@ class Boolean(Scalar):
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def parse_literal(ast):
|
def parse_literal(ast):
|
||||||
if isinstance(ast, BooleanValue):
|
if isinstance(ast, BooleanValueNode):
|
||||||
return ast.value
|
return ast.value
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -6,13 +6,13 @@ from graphql.type.directives import (
|
||||||
GraphQLIncludeDirective,
|
GraphQLIncludeDirective,
|
||||||
GraphQLSkipDirective,
|
GraphQLSkipDirective,
|
||||||
)
|
)
|
||||||
from graphql.type.introspection import IntrospectionSchema
|
from graphql.type.introspection import introspection_types
|
||||||
from graphql.utils.introspection_query import introspection_query
|
from graphql.utilities.introspection_query import get_introspection_query
|
||||||
from graphql.utils.schema_printer import print_schema
|
from graphql.utilities.schema_printer import print_schema
|
||||||
|
|
||||||
from .definitions import GrapheneGraphQLType
|
from .definitions import GrapheneGraphQLType
|
||||||
from .objecttype import ObjectType
|
from .objecttype import ObjectType
|
||||||
from .typemap import TypeMap, is_graphene_type
|
from .typemap import is_graphene_type
|
||||||
|
|
||||||
|
|
||||||
def assert_valid_root_type(_type):
|
def assert_valid_root_type(_type):
|
||||||
|
@ -25,103 +25,5 @@ def assert_valid_root_type(_type):
|
||||||
).format(_type)
|
).format(_type)
|
||||||
|
|
||||||
|
|
||||||
class Schema(GraphQLSchema):
|
Schema = GraphQLSchema
|
||||||
"""
|
|
||||||
Schema Definition
|
|
||||||
|
|
||||||
A Schema is created by supplying the root types of each type of operation,
|
|
||||||
query and mutation (optional).
|
|
||||||
"""
|
|
||||||
|
|
||||||
def __init__(
|
|
||||||
self,
|
|
||||||
query=None,
|
|
||||||
mutation=None,
|
|
||||||
subscription=None,
|
|
||||||
directives=None,
|
|
||||||
types=None,
|
|
||||||
auto_camelcase=True,
|
|
||||||
):
|
|
||||||
assert_valid_root_type(query)
|
|
||||||
assert_valid_root_type(mutation)
|
|
||||||
assert_valid_root_type(subscription)
|
|
||||||
self._query = query
|
|
||||||
self._mutation = mutation
|
|
||||||
self._subscription = subscription
|
|
||||||
self.types = types
|
|
||||||
self.auto_camelcase = auto_camelcase
|
|
||||||
if directives is None:
|
|
||||||
directives = [GraphQLIncludeDirective, GraphQLSkipDirective]
|
|
||||||
|
|
||||||
assert all(
|
|
||||||
isinstance(d, GraphQLDirective) for d in directives
|
|
||||||
), "Schema directives must be List[GraphQLDirective] if provided but got: {}.".format(
|
|
||||||
directives
|
|
||||||
)
|
|
||||||
self._directives = directives
|
|
||||||
self.build_typemap()
|
|
||||||
|
|
||||||
def get_query_type(self):
|
|
||||||
return self.get_graphql_type(self._query)
|
|
||||||
|
|
||||||
def get_mutation_type(self):
|
|
||||||
return self.get_graphql_type(self._mutation)
|
|
||||||
|
|
||||||
def get_subscription_type(self):
|
|
||||||
return self.get_graphql_type(self._subscription)
|
|
||||||
|
|
||||||
def __getattr__(self, type_name):
|
|
||||||
"""
|
|
||||||
This function let the developer select a type in a given schema
|
|
||||||
by accessing its attrs.
|
|
||||||
|
|
||||||
Example: using schema.Query for accessing the "Query" type in the Schema
|
|
||||||
"""
|
|
||||||
_type = super(Schema, self).get_type(type_name)
|
|
||||||
if _type is None:
|
|
||||||
raise AttributeError('Type "{}" not found in the Schema'.format(type_name))
|
|
||||||
if isinstance(_type, GrapheneGraphQLType):
|
|
||||||
return _type.graphene_type
|
|
||||||
return _type
|
|
||||||
|
|
||||||
def get_graphql_type(self, _type):
|
|
||||||
if not _type:
|
|
||||||
return _type
|
|
||||||
if is_type(_type):
|
|
||||||
return _type
|
|
||||||
if is_graphene_type(_type):
|
|
||||||
graphql_type = self.get_type(_type._meta.name)
|
|
||||||
assert graphql_type, "Type {} not found in this schema.".format(
|
|
||||||
_type._meta.name
|
|
||||||
)
|
|
||||||
assert graphql_type.graphene_type == _type
|
|
||||||
return graphql_type
|
|
||||||
raise Exception("{} is not a valid GraphQL type.".format(_type))
|
|
||||||
|
|
||||||
def execute(self, *args, **kwargs):
|
|
||||||
return graphql(self, *args, **kwargs)
|
|
||||||
|
|
||||||
def introspect(self):
|
|
||||||
instrospection = self.execute(introspection_query)
|
|
||||||
if instrospection.errors:
|
|
||||||
raise instrospection.errors[0]
|
|
||||||
return instrospection.data
|
|
||||||
|
|
||||||
def __str__(self):
|
|
||||||
return print_schema(self)
|
|
||||||
|
|
||||||
def lazy(self, _type):
|
|
||||||
return lambda: self.get_type(_type)
|
|
||||||
|
|
||||||
def build_typemap(self):
|
|
||||||
initial_types = [
|
|
||||||
self._query,
|
|
||||||
self._mutation,
|
|
||||||
self._subscription,
|
|
||||||
IntrospectionSchema,
|
|
||||||
]
|
|
||||||
if self.types:
|
|
||||||
initial_types += self.types
|
|
||||||
self._type_map = TypeMap(
|
|
||||||
initial_types, auto_camelcase=self.auto_camelcase, schema=self
|
|
||||||
)
|
|
||||||
|
|
|
@ -156,7 +156,7 @@ def test_bad_variables():
|
||||||
)
|
)
|
||||||
assert len(result.errors) == 1
|
assert len(result.errors) == 1
|
||||||
# when `input` is not JSON serializable formatting the error message in
|
# when `input` is not JSON serializable formatting the error message in
|
||||||
# `graphql.utils.is_valid_value` line 79 fails with a TypeError
|
# `graphql.utilities.is_valid_value` line 79 fails with a TypeError
|
||||||
assert isinstance(result.errors[0], GraphQLError)
|
assert isinstance(result.errors[0], GraphQLError)
|
||||||
print(result.errors[0])
|
print(result.errors[0])
|
||||||
assert result.data is None
|
assert result.data is None
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import six
|
import six
|
||||||
|
|
||||||
from ..argument import Argument
|
from ..argument import Argument
|
||||||
from ..enum import Enum, PyEnum
|
from ..enum import Enum
|
||||||
from ..field import Field
|
from ..field import Field
|
||||||
from ..inputfield import InputField
|
from ..inputfield import InputField
|
||||||
from ..schema import ObjectType, Schema
|
from ..schema import ObjectType, Schema
|
||||||
|
@ -52,88 +52,57 @@ def test_enum_instance_construction():
|
||||||
assert sorted([v.name for v in values]) == ["BLUE", "GREEN", "RED"]
|
assert sorted([v.name for v in values]) == ["BLUE", "GREEN", "RED"]
|
||||||
|
|
||||||
|
|
||||||
def test_enum_from_builtin_enum():
|
|
||||||
PyRGB = PyEnum("RGB", "RED,GREEN,BLUE")
|
|
||||||
|
|
||||||
RGB = Enum.from_enum(PyRGB)
|
# def test_enum_from_builtin_enum_accepts_lambda_description():
|
||||||
assert RGB._meta.enum == PyRGB
|
# def custom_description(value):
|
||||||
assert RGB.RED
|
# if not value:
|
||||||
assert RGB.GREEN
|
# return "StarWars Episodes"
|
||||||
assert RGB.BLUE
|
|
||||||
|
|
||||||
|
# return "New Hope Episode" if value == Episode.NEWHOPE else "Other"
|
||||||
|
|
||||||
def test_enum_from_builtin_enum_accepts_lambda_description():
|
# def custom_deprecation_reason(value):
|
||||||
def custom_description(value):
|
# return "meh" if value == Episode.NEWHOPE else None
|
||||||
if not value:
|
|
||||||
return "StarWars Episodes"
|
|
||||||
|
|
||||||
return "New Hope Episode" if value == Episode.NEWHOPE else "Other"
|
# PyEpisode = PyEnum("PyEpisode", "NEWHOPE,EMPIRE,JEDI")
|
||||||
|
# Episode = Enum.from_enum(
|
||||||
|
# PyEpisode,
|
||||||
|
# description=custom_description,
|
||||||
|
# deprecation_reason=custom_deprecation_reason,
|
||||||
|
# )
|
||||||
|
|
||||||
def custom_deprecation_reason(value):
|
# class Query(ObjectType):
|
||||||
return "meh" if value == Episode.NEWHOPE else None
|
# foo = Episode()
|
||||||
|
|
||||||
PyEpisode = PyEnum("PyEpisode", "NEWHOPE,EMPIRE,JEDI")
|
# schema = Schema(query=Query)
|
||||||
Episode = Enum.from_enum(
|
|
||||||
PyEpisode,
|
|
||||||
description=custom_description,
|
|
||||||
deprecation_reason=custom_deprecation_reason,
|
|
||||||
)
|
|
||||||
|
|
||||||
class Query(ObjectType):
|
# GraphQLPyEpisode = schema._type_map["PyEpisode"].values
|
||||||
foo = Episode()
|
|
||||||
|
|
||||||
schema = Schema(query=Query)
|
# assert schema._type_map["PyEpisode"].description == "StarWars Episodes"
|
||||||
|
# assert (
|
||||||
|
# GraphQLPyEpisode[0].name == "NEWHOPE"
|
||||||
|
# and GraphQLPyEpisode[0].description == "New Hope Episode"
|
||||||
|
# )
|
||||||
|
# assert (
|
||||||
|
# GraphQLPyEpisode[1].name == "EMPIRE"
|
||||||
|
# and GraphQLPyEpisode[1].description == "Other"
|
||||||
|
# )
|
||||||
|
# assert (
|
||||||
|
# GraphQLPyEpisode[2].name == "JEDI"
|
||||||
|
# and GraphQLPyEpisode[2].description == "Other"
|
||||||
|
# )
|
||||||
|
|
||||||
GraphQLPyEpisode = schema._type_map["PyEpisode"].values
|
# assert (
|
||||||
|
# GraphQLPyEpisode[0].name == "NEWHOPE"
|
||||||
assert schema._type_map["PyEpisode"].description == "StarWars Episodes"
|
# and GraphQLPyEpisode[0].deprecation_reason == "meh"
|
||||||
assert (
|
# )
|
||||||
GraphQLPyEpisode[0].name == "NEWHOPE"
|
# assert (
|
||||||
and GraphQLPyEpisode[0].description == "New Hope Episode"
|
# GraphQLPyEpisode[1].name == "EMPIRE"
|
||||||
)
|
# and GraphQLPyEpisode[1].deprecation_reason is None
|
||||||
assert (
|
# )
|
||||||
GraphQLPyEpisode[1].name == "EMPIRE"
|
# assert (
|
||||||
and GraphQLPyEpisode[1].description == "Other"
|
# GraphQLPyEpisode[2].name == "JEDI"
|
||||||
)
|
# and GraphQLPyEpisode[2].deprecation_reason is None
|
||||||
assert (
|
# )
|
||||||
GraphQLPyEpisode[2].name == "JEDI"
|
|
||||||
and GraphQLPyEpisode[2].description == "Other"
|
|
||||||
)
|
|
||||||
|
|
||||||
assert (
|
|
||||||
GraphQLPyEpisode[0].name == "NEWHOPE"
|
|
||||||
and GraphQLPyEpisode[0].deprecation_reason == "meh"
|
|
||||||
)
|
|
||||||
assert (
|
|
||||||
GraphQLPyEpisode[1].name == "EMPIRE"
|
|
||||||
and GraphQLPyEpisode[1].deprecation_reason is None
|
|
||||||
)
|
|
||||||
assert (
|
|
||||||
GraphQLPyEpisode[2].name == "JEDI"
|
|
||||||
and GraphQLPyEpisode[2].deprecation_reason is None
|
|
||||||
)
|
|
||||||
|
|
||||||
|
|
||||||
def test_enum_from_python3_enum_uses_enum_doc():
|
|
||||||
if not six.PY3:
|
|
||||||
return
|
|
||||||
|
|
||||||
from enum import Enum as PyEnum
|
|
||||||
|
|
||||||
class Color(PyEnum):
|
|
||||||
"""This is the description"""
|
|
||||||
|
|
||||||
RED = 1
|
|
||||||
GREEN = 2
|
|
||||||
BLUE = 3
|
|
||||||
|
|
||||||
RGB = Enum.from_enum(Color)
|
|
||||||
assert RGB._meta.enum == Color
|
|
||||||
assert RGB._meta.description == "This is the description"
|
|
||||||
assert RGB
|
|
||||||
assert RGB.RED
|
|
||||||
assert RGB.GREEN
|
|
||||||
assert RGB.BLUE
|
|
||||||
|
|
||||||
|
|
||||||
def test_enum_value_from_class():
|
def test_enum_value_from_class():
|
||||||
|
|
|
@ -1,7 +1,7 @@
|
||||||
import json
|
import json
|
||||||
from functools import partial
|
from functools import partial
|
||||||
|
|
||||||
from graphql import GraphQLError, ResolveInfo, Source, execute, parse
|
from graphql import GraphQLError, GraphQLResolveInfo, Source, execute, parse
|
||||||
|
|
||||||
from ..context import Context
|
from ..context import Context
|
||||||
from ..dynamic import Dynamic
|
from ..dynamic import Dynamic
|
||||||
|
@ -455,7 +455,7 @@ def test_query_annotated_resolvers():
|
||||||
return "{}-{}".format(self, info.context.key)
|
return "{}-{}".format(self, info.context.key)
|
||||||
|
|
||||||
def resolve_info(self, info):
|
def resolve_info(self, info):
|
||||||
assert isinstance(info, ResolveInfo)
|
assert isinstance(info, GraphQLResolveInfo)
|
||||||
return "{}-{}".format(self, info.field_name)
|
return "{}-{}".format(self, info.field_name)
|
||||||
|
|
||||||
test_schema = Schema(Query)
|
test_schema = Schema(Query)
|
||||||
|
|
|
@ -1,286 +1,286 @@
|
||||||
import pytest
|
# import pytest
|
||||||
from graphql.type import (
|
# from graphql.type import (
|
||||||
GraphQLArgument,
|
# GraphQLArgument,
|
||||||
GraphQLEnumType,
|
# GraphQLEnumType,
|
||||||
GraphQLEnumValue,
|
# GraphQLEnumValue,
|
||||||
GraphQLField,
|
# GraphQLField,
|
||||||
GraphQLInputObjectField,
|
# GraphQLInputField,
|
||||||
GraphQLInputObjectType,
|
# GraphQLInputObjectType,
|
||||||
GraphQLInterfaceType,
|
# GraphQLInterfaceType,
|
||||||
GraphQLObjectType,
|
# GraphQLObjectType,
|
||||||
GraphQLString,
|
# GraphQLString,
|
||||||
)
|
# )
|
||||||
|
|
||||||
from ..dynamic import Dynamic
|
# from ..dynamic import Dynamic
|
||||||
from ..enum import Enum
|
# from ..enum import Enum
|
||||||
from ..field import Field
|
# from ..field import Field
|
||||||
from ..inputfield import InputField
|
# from ..inputfield import InputField
|
||||||
from ..inputobjecttype import InputObjectType
|
# from ..inputobjecttype import InputObjectType
|
||||||
from ..interface import Interface
|
# 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 ..typemap import TypeMap, resolve_type
|
# from ..typemap import resolve_type
|
||||||
|
|
||||||
|
|
||||||
def test_enum():
|
# def test_enum():
|
||||||
class MyEnum(Enum):
|
# class MyEnum(Enum):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo = 1
|
# foo = 1
|
||||||
bar = 2
|
# bar = 2
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def description(self):
|
# def description(self):
|
||||||
return "Description {}={}".format(self.name, self.value)
|
# return "Description {}={}".format(self.name, self.value)
|
||||||
|
|
||||||
@property
|
# @property
|
||||||
def deprecation_reason(self):
|
# def deprecation_reason(self):
|
||||||
if self == MyEnum.foo:
|
# if self == MyEnum.foo:
|
||||||
return "Is deprecated"
|
# return "Is deprecated"
|
||||||
|
|
||||||
typemap = TypeMap([MyEnum])
|
# typemap = TypeMap([MyEnum])
|
||||||
assert "MyEnum" in typemap
|
# assert "MyEnum" in typemap
|
||||||
graphql_enum = typemap["MyEnum"]
|
# graphql_enum = typemap["MyEnum"]
|
||||||
assert isinstance(graphql_enum, GraphQLEnumType)
|
# assert isinstance(graphql_enum, GraphQLEnumType)
|
||||||
assert graphql_enum.name == "MyEnum"
|
# assert graphql_enum.name == "MyEnum"
|
||||||
assert graphql_enum.description == "Description"
|
# assert graphql_enum.description == "Description"
|
||||||
values = graphql_enum.values
|
# values = graphql_enum.values
|
||||||
assert values == [
|
# assert values == [
|
||||||
GraphQLEnumValue(
|
# GraphQLEnumValue(
|
||||||
name="foo",
|
# name="foo",
|
||||||
value=1,
|
# value=1,
|
||||||
description="Description foo=1",
|
# description="Description foo=1",
|
||||||
deprecation_reason="Is deprecated",
|
# deprecation_reason="Is deprecated",
|
||||||
),
|
# ),
|
||||||
GraphQLEnumValue(name="bar", value=2, description="Description bar=2"),
|
# GraphQLEnumValue(name="bar", value=2, description="Description bar=2"),
|
||||||
]
|
# ]
|
||||||
|
|
||||||
|
|
||||||
def test_objecttype():
|
# def test_objecttype():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo = String(
|
# foo = String(
|
||||||
bar=String(description="Argument description", default_value="x"),
|
# bar=String(description="Argument description", default_value="x"),
|
||||||
description="Field description",
|
# description="Field description",
|
||||||
)
|
# )
|
||||||
bar = String(name="gizmo")
|
# bar = String(name="gizmo")
|
||||||
|
|
||||||
def resolve_foo(self, bar):
|
# def resolve_foo(self, bar):
|
||||||
return bar
|
# return bar
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType])
|
# typemap = TypeMap([MyObjectType])
|
||||||
assert "MyObjectType" in typemap
|
# assert "MyObjectType" in typemap
|
||||||
graphql_type = typemap["MyObjectType"]
|
# graphql_type = typemap["MyObjectType"]
|
||||||
assert isinstance(graphql_type, GraphQLObjectType)
|
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||||
assert graphql_type.name == "MyObjectType"
|
# assert graphql_type.name == "MyObjectType"
|
||||||
assert graphql_type.description == "Description"
|
# assert graphql_type.description == "Description"
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["foo", "gizmo"]
|
# assert list(fields.keys()) == ["foo", "gizmo"]
|
||||||
foo_field = fields["foo"]
|
# foo_field = fields["foo"]
|
||||||
assert isinstance(foo_field, GraphQLField)
|
# assert isinstance(foo_field, GraphQLField)
|
||||||
assert foo_field.description == "Field description"
|
# assert foo_field.description == "Field description"
|
||||||
|
|
||||||
assert foo_field.args == {
|
# assert foo_field.args == {
|
||||||
"bar": GraphQLArgument(
|
# "bar": GraphQLArgument(
|
||||||
GraphQLString,
|
# GraphQLString,
|
||||||
description="Argument description",
|
# description="Argument description",
|
||||||
default_value="x",
|
# default_value="x",
|
||||||
out_name="bar",
|
# out_name="bar",
|
||||||
)
|
# )
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
|
||||||
def test_dynamic_objecttype():
|
# def test_dynamic_objecttype():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
bar = Dynamic(lambda: Field(String))
|
# bar = Dynamic(lambda: Field(String))
|
||||||
own = Field(lambda: MyObjectType)
|
# own = Field(lambda: MyObjectType)
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType])
|
# typemap = TypeMap([MyObjectType])
|
||||||
assert "MyObjectType" in typemap
|
# assert "MyObjectType" in typemap
|
||||||
assert list(MyObjectType._meta.fields.keys()) == ["bar", "own"]
|
# assert list(MyObjectType._meta.fields.keys()) == ["bar", "own"]
|
||||||
graphql_type = typemap["MyObjectType"]
|
# graphql_type = typemap["MyObjectType"]
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["bar", "own"]
|
# assert list(fields.keys()) == ["bar", "own"]
|
||||||
assert fields["bar"].type == GraphQLString
|
# assert fields["bar"].type == GraphQLString
|
||||||
assert fields["own"].type == graphql_type
|
# assert fields["own"].type == graphql_type
|
||||||
|
|
||||||
|
|
||||||
def test_interface():
|
# def test_interface():
|
||||||
class MyInterface(Interface):
|
# class MyInterface(Interface):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo = String(
|
# foo = String(
|
||||||
bar=String(description="Argument description", default_value="x"),
|
# bar=String(description="Argument description", default_value="x"),
|
||||||
description="Field description",
|
# description="Field description",
|
||||||
)
|
# )
|
||||||
bar = String(name="gizmo", first_arg=String(), other_arg=String(name="oth_arg"))
|
# bar = String(name="gizmo", first_arg=String(), other_arg=String(name="oth_arg"))
|
||||||
own = Field(lambda: MyInterface)
|
# own = Field(lambda: MyInterface)
|
||||||
|
|
||||||
def resolve_foo(self, args, info):
|
# def resolve_foo(self, args, info):
|
||||||
return args.get("bar")
|
# return args.get("bar")
|
||||||
|
|
||||||
typemap = TypeMap([MyInterface])
|
# typemap = TypeMap([MyInterface])
|
||||||
assert "MyInterface" in typemap
|
# assert "MyInterface" in typemap
|
||||||
graphql_type = typemap["MyInterface"]
|
# graphql_type = typemap["MyInterface"]
|
||||||
assert isinstance(graphql_type, GraphQLInterfaceType)
|
# assert isinstance(graphql_type, GraphQLInterfaceType)
|
||||||
assert graphql_type.name == "MyInterface"
|
# assert graphql_type.name == "MyInterface"
|
||||||
assert graphql_type.description == "Description"
|
# assert graphql_type.description == "Description"
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["foo", "gizmo", "own"]
|
# assert list(fields.keys()) == ["foo", "gizmo", "own"]
|
||||||
assert fields["own"].type == graphql_type
|
# assert fields["own"].type == graphql_type
|
||||||
assert list(fields["gizmo"].args.keys()) == ["firstArg", "oth_arg"]
|
# assert list(fields["gizmo"].args.keys()) == ["firstArg", "oth_arg"]
|
||||||
foo_field = fields["foo"]
|
# foo_field = fields["foo"]
|
||||||
assert isinstance(foo_field, GraphQLField)
|
# assert isinstance(foo_field, GraphQLField)
|
||||||
assert foo_field.description == "Field description"
|
# assert foo_field.description == "Field description"
|
||||||
assert not foo_field.resolver # Resolver not attached in interfaces
|
# assert not foo_field.resolver # Resolver not attached in interfaces
|
||||||
assert foo_field.args == {
|
# assert foo_field.args == {
|
||||||
"bar": GraphQLArgument(
|
# "bar": GraphQLArgument(
|
||||||
GraphQLString,
|
# GraphQLString,
|
||||||
description="Argument description",
|
# description="Argument description",
|
||||||
default_value="x",
|
# default_value="x",
|
||||||
out_name="bar",
|
# out_name="bar",
|
||||||
)
|
# )
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
|
||||||
def test_inputobject():
|
# def test_inputobject():
|
||||||
class OtherObjectType(InputObjectType):
|
# class OtherObjectType(InputObjectType):
|
||||||
thingy = NonNull(Int)
|
# thingy = NonNull(Int)
|
||||||
|
|
||||||
class MyInnerObjectType(InputObjectType):
|
# class MyInnerObjectType(InputObjectType):
|
||||||
some_field = String()
|
# some_field = String()
|
||||||
some_other_field = List(OtherObjectType)
|
# some_other_field = List(OtherObjectType)
|
||||||
|
|
||||||
class MyInputObjectType(InputObjectType):
|
# class MyInputObjectType(InputObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo_bar = String(description="Field description")
|
# foo_bar = String(description="Field description")
|
||||||
bar = String(name="gizmo")
|
# bar = String(name="gizmo")
|
||||||
baz = NonNull(MyInnerObjectType)
|
# baz = NonNull(MyInnerObjectType)
|
||||||
own = InputField(lambda: MyInputObjectType)
|
# own = InputField(lambda: MyInputObjectType)
|
||||||
|
|
||||||
def resolve_foo_bar(self, args, info):
|
# def resolve_foo_bar(self, args, info):
|
||||||
return args.get("bar")
|
# return args.get("bar")
|
||||||
|
|
||||||
typemap = TypeMap([MyInputObjectType])
|
# typemap = TypeMap([MyInputObjectType])
|
||||||
assert "MyInputObjectType" in typemap
|
# assert "MyInputObjectType" in typemap
|
||||||
graphql_type = typemap["MyInputObjectType"]
|
# graphql_type = typemap["MyInputObjectType"]
|
||||||
assert isinstance(graphql_type, GraphQLInputObjectType)
|
# assert isinstance(graphql_type, GraphQLInputObjectType)
|
||||||
assert graphql_type.name == "MyInputObjectType"
|
# assert graphql_type.name == "MyInputObjectType"
|
||||||
assert graphql_type.description == "Description"
|
# assert graphql_type.description == "Description"
|
||||||
|
|
||||||
other_graphql_type = typemap["OtherObjectType"]
|
# other_graphql_type = typemap["OtherObjectType"]
|
||||||
inner_graphql_type = typemap["MyInnerObjectType"]
|
# inner_graphql_type = typemap["MyInnerObjectType"]
|
||||||
container = graphql_type.create_container(
|
# container = graphql_type.create_container(
|
||||||
{
|
# {
|
||||||
"bar": "oh!",
|
# "bar": "oh!",
|
||||||
"baz": inner_graphql_type.create_container(
|
# "baz": inner_graphql_type.create_container(
|
||||||
{
|
# {
|
||||||
"some_other_field": [
|
# "some_other_field": [
|
||||||
other_graphql_type.create_container({"thingy": 1}),
|
# other_graphql_type.create_container({"thingy": 1}),
|
||||||
other_graphql_type.create_container({"thingy": 2}),
|
# other_graphql_type.create_container({"thingy": 2}),
|
||||||
]
|
# ]
|
||||||
}
|
# }
|
||||||
),
|
# ),
|
||||||
}
|
# }
|
||||||
)
|
# )
|
||||||
assert isinstance(container, MyInputObjectType)
|
# assert isinstance(container, MyInputObjectType)
|
||||||
assert "bar" in container
|
# assert "bar" in container
|
||||||
assert container.bar == "oh!"
|
# assert container.bar == "oh!"
|
||||||
assert "foo_bar" not in container
|
# assert "foo_bar" not in container
|
||||||
assert container.foo_bar is None
|
# assert container.foo_bar is None
|
||||||
assert container.baz.some_field is None
|
# assert container.baz.some_field is None
|
||||||
assert container.baz.some_other_field[0].thingy == 1
|
# assert container.baz.some_other_field[0].thingy == 1
|
||||||
assert container.baz.some_other_field[1].thingy == 2
|
# assert container.baz.some_other_field[1].thingy == 2
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["fooBar", "gizmo", "baz", "own"]
|
# assert list(fields.keys()) == ["fooBar", "gizmo", "baz", "own"]
|
||||||
own_field = fields["own"]
|
# own_field = fields["own"]
|
||||||
assert own_field.type == graphql_type
|
# assert own_field.type == graphql_type
|
||||||
foo_field = fields["fooBar"]
|
# foo_field = fields["fooBar"]
|
||||||
assert isinstance(foo_field, GraphQLInputObjectField)
|
# assert isinstance(foo_field, GraphQLInputObjectField)
|
||||||
assert foo_field.description == "Field description"
|
# assert foo_field.description == "Field description"
|
||||||
|
|
||||||
|
|
||||||
def test_objecttype_camelcase():
|
# def test_objecttype_camelcase():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo_bar = String(bar_foo=String())
|
# foo_bar = String(bar_foo=String())
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType])
|
# typemap = TypeMap([MyObjectType])
|
||||||
assert "MyObjectType" in typemap
|
# assert "MyObjectType" in typemap
|
||||||
graphql_type = typemap["MyObjectType"]
|
# graphql_type = typemap["MyObjectType"]
|
||||||
assert isinstance(graphql_type, GraphQLObjectType)
|
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||||
assert graphql_type.name == "MyObjectType"
|
# assert graphql_type.name == "MyObjectType"
|
||||||
assert graphql_type.description == "Description"
|
# assert graphql_type.description == "Description"
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["fooBar"]
|
# assert list(fields.keys()) == ["fooBar"]
|
||||||
foo_field = fields["fooBar"]
|
# foo_field = fields["fooBar"]
|
||||||
assert isinstance(foo_field, GraphQLField)
|
# assert isinstance(foo_field, GraphQLField)
|
||||||
assert foo_field.args == {
|
# assert foo_field.args == {
|
||||||
"barFoo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
# "barFoo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
|
||||||
def test_objecttype_camelcase_disabled():
|
# def test_objecttype_camelcase_disabled():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
foo_bar = String(bar_foo=String())
|
# foo_bar = String(bar_foo=String())
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType], auto_camelcase=False)
|
# typemap = TypeMap([MyObjectType], auto_camelcase=False)
|
||||||
assert "MyObjectType" in typemap
|
# assert "MyObjectType" in typemap
|
||||||
graphql_type = typemap["MyObjectType"]
|
# graphql_type = typemap["MyObjectType"]
|
||||||
assert isinstance(graphql_type, GraphQLObjectType)
|
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||||
assert graphql_type.name == "MyObjectType"
|
# assert graphql_type.name == "MyObjectType"
|
||||||
assert graphql_type.description == "Description"
|
# assert graphql_type.description == "Description"
|
||||||
|
|
||||||
fields = graphql_type.fields
|
# fields = graphql_type.fields
|
||||||
assert list(fields.keys()) == ["foo_bar"]
|
# assert list(fields.keys()) == ["foo_bar"]
|
||||||
foo_field = fields["foo_bar"]
|
# foo_field = fields["foo_bar"]
|
||||||
assert isinstance(foo_field, GraphQLField)
|
# assert isinstance(foo_field, GraphQLField)
|
||||||
assert foo_field.args == {
|
# assert foo_field.args == {
|
||||||
"bar_foo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
# "bar_foo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||||
}
|
# }
|
||||||
|
|
||||||
|
|
||||||
def test_objecttype_with_possible_types():
|
# def test_objecttype_with_possible_types():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
"""Description"""
|
# """Description"""
|
||||||
|
|
||||||
class Meta:
|
# class Meta:
|
||||||
possible_types = (dict,)
|
# possible_types = (dict,)
|
||||||
|
|
||||||
foo_bar = String()
|
# foo_bar = String()
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType])
|
# typemap = TypeMap([MyObjectType])
|
||||||
graphql_type = typemap["MyObjectType"]
|
# graphql_type = typemap["MyObjectType"]
|
||||||
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():
|
# def test_resolve_type_with_missing_type():
|
||||||
class MyObjectType(ObjectType):
|
# class MyObjectType(ObjectType):
|
||||||
foo_bar = String()
|
# foo_bar = String()
|
||||||
|
|
||||||
class MyOtherObjectType(ObjectType):
|
# class MyOtherObjectType(ObjectType):
|
||||||
fizz_buzz = String()
|
# fizz_buzz = String()
|
||||||
|
|
||||||
def resolve_type_func(root, info):
|
# def resolve_type_func(root, info):
|
||||||
return MyOtherObjectType
|
# return MyOtherObjectType
|
||||||
|
|
||||||
typemap = TypeMap([MyObjectType])
|
# typemap = TypeMap([MyObjectType])
|
||||||
with pytest.raises(AssertionError) as excinfo:
|
# with pytest.raises(AssertionError) as excinfo:
|
||||||
resolve_type(resolve_type_func, typemap, "MyOtherObjectType", {}, {})
|
# resolve_type(resolve_type_func, typemap, "MyOtherObjectType", {}, {})
|
||||||
|
|
||||||
assert "MyOtherObjectTyp" in str(excinfo.value)
|
# assert "MyOtherObjectTyp" in str(excinfo.value)
|
||||||
|
|
|
@ -9,7 +9,6 @@ class Query(ObjectType):
|
||||||
def resolve_uuid(self, info, input):
|
def resolve_uuid(self, info, input):
|
||||||
return input
|
return input
|
||||||
|
|
||||||
|
|
||||||
schema = Schema(query=Query)
|
schema = Schema(query=Query)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -8,15 +8,14 @@ from graphql import (
|
||||||
GraphQLField,
|
GraphQLField,
|
||||||
GraphQLFloat,
|
GraphQLFloat,
|
||||||
GraphQLID,
|
GraphQLID,
|
||||||
GraphQLInputObjectField,
|
GraphQLInputField,
|
||||||
GraphQLInt,
|
GraphQLInt,
|
||||||
GraphQLList,
|
GraphQLList,
|
||||||
GraphQLNonNull,
|
GraphQLNonNull,
|
||||||
GraphQLString,
|
GraphQLString,
|
||||||
)
|
)
|
||||||
from graphql.execution.executor import get_default_resolve_type_fn
|
from graphql.execution.execute import default_type_resolver
|
||||||
from graphql.type import GraphQLEnumValue
|
from graphql.type import GraphQLEnumValue
|
||||||
from graphql.type.typemap import GraphQLTypeMap
|
|
||||||
|
|
||||||
from ..utils.get_unbound_function import get_unbound_function
|
from ..utils.get_unbound_function import get_unbound_function
|
||||||
from ..utils.str_converters import to_camel_case
|
from ..utils.str_converters import to_camel_case
|
||||||
|
@ -56,7 +55,7 @@ def resolve_type(resolve_type_func, map, type_name, root, info):
|
||||||
|
|
||||||
if not _type:
|
if not _type:
|
||||||
return_type = map[type_name]
|
return_type = map[type_name]
|
||||||
return get_default_resolve_type_fn(root, info, return_type)
|
return default_type_resolver(root, info, return_type)
|
||||||
|
|
||||||
if inspect.isclass(_type) and issubclass(_type, ObjectType):
|
if inspect.isclass(_type) and issubclass(_type, ObjectType):
|
||||||
graphql_type = map.get(_type._meta.name)
|
graphql_type = map.get(_type._meta.name)
|
||||||
|
@ -73,265 +72,266 @@ def is_type_of_from_possible_types(possible_types, root, info):
|
||||||
return isinstance(root, possible_types)
|
return isinstance(root, possible_types)
|
||||||
|
|
||||||
|
|
||||||
class TypeMap(GraphQLTypeMap):
|
# class TypeMap(object):
|
||||||
def __init__(self, types, auto_camelcase=True, schema=None):
|
# def __init__(self, types, auto_camelcase=True, schema=None):
|
||||||
self.auto_camelcase = auto_camelcase
|
# self.auto_camelcase = auto_camelcase
|
||||||
self.schema = schema
|
# self.schema = schema
|
||||||
super(TypeMap, self).__init__(types)
|
# types = [t for t in types if t]
|
||||||
|
# super(TypeMap, self).__init__(types)
|
||||||
|
|
||||||
def reducer(self, map, type):
|
# def reducer(self, map, type):
|
||||||
if not type:
|
# if not type:
|
||||||
return map
|
# return map
|
||||||
if inspect.isfunction(type):
|
# if inspect.isfunction(type):
|
||||||
type = type()
|
# type = type()
|
||||||
if is_graphene_type(type):
|
# if is_graphene_type(type):
|
||||||
return self.graphene_reducer(map, type)
|
# return self.graphene_reducer(map, type)
|
||||||
return GraphQLTypeMap.reducer(map, type)
|
# return GraphQLSchema.reducer(map, type)
|
||||||
|
|
||||||
def graphene_reducer(self, map, type):
|
# def graphene_reducer(self, map, type):
|
||||||
if isinstance(type, (List, NonNull)):
|
# if isinstance(type, (List, NonNull)):
|
||||||
return self.reducer(map, type.of_type)
|
# return self.reducer(map, type.of_type)
|
||||||
if type._meta.name in map:
|
# if type._meta.name in map:
|
||||||
_type = map[type._meta.name]
|
# _type = map[type._meta.name]
|
||||||
if isinstance(_type, GrapheneGraphQLType):
|
# if isinstance(_type, GrapheneGraphQLType):
|
||||||
assert _type.graphene_type == type, (
|
# assert _type.graphene_type == type, (
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
# "Found different types with the same name in the schema: {}, {}."
|
||||||
).format(_type.graphene_type, type)
|
# ).format(_type.graphene_type, type)
|
||||||
return map
|
# return map
|
||||||
|
|
||||||
if issubclass(type, ObjectType):
|
# if issubclass(type, ObjectType):
|
||||||
internal_type = self.construct_objecttype(map, type)
|
# internal_type = self.construct_objecttype(map, type)
|
||||||
elif issubclass(type, InputObjectType):
|
# elif issubclass(type, InputObjectType):
|
||||||
internal_type = self.construct_inputobjecttype(map, type)
|
# internal_type = self.construct_inputobjecttype(map, type)
|
||||||
elif issubclass(type, Interface):
|
# elif issubclass(type, Interface):
|
||||||
internal_type = self.construct_interface(map, type)
|
# internal_type = self.construct_interface(map, type)
|
||||||
elif issubclass(type, Scalar):
|
# elif issubclass(type, Scalar):
|
||||||
internal_type = self.construct_scalar(map, type)
|
# internal_type = self.construct_scalar(map, type)
|
||||||
elif issubclass(type, Enum):
|
# elif issubclass(type, Enum):
|
||||||
internal_type = self.construct_enum(map, type)
|
# internal_type = self.construct_enum(map, type)
|
||||||
elif issubclass(type, Union):
|
# elif issubclass(type, Union):
|
||||||
internal_type = self.construct_union(map, type)
|
# internal_type = self.construct_union(map, type)
|
||||||
else:
|
# else:
|
||||||
raise Exception("Expected Graphene type, but received: {}.".format(type))
|
# raise Exception("Expected Graphene type, but received: {}.".format(type))
|
||||||
|
|
||||||
return GraphQLTypeMap.reducer(map, internal_type)
|
# return GraphQLSchema.reducer(map, internal_type)
|
||||||
|
|
||||||
def construct_scalar(self, map, type):
|
# def construct_scalar(self, map, 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 = {
|
||||||
String: GraphQLString,
|
# String: GraphQLString,
|
||||||
Int: GraphQLInt,
|
# Int: GraphQLInt,
|
||||||
Float: GraphQLFloat,
|
# Float: GraphQLFloat,
|
||||||
Boolean: GraphQLBoolean,
|
# Boolean: GraphQLBoolean,
|
||||||
ID: GraphQLID,
|
# ID: GraphQLID,
|
||||||
}
|
# }
|
||||||
if type in _scalars:
|
# if type in _scalars:
|
||||||
return _scalars[type]
|
# return _scalars[type]
|
||||||
|
|
||||||
return GrapheneScalarType(
|
# return GrapheneScalarType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type._meta.description,
|
# description=type._meta.description,
|
||||||
serialize=getattr(type, "serialize", None),
|
# serialize=getattr(type, "serialize", None),
|
||||||
parse_value=getattr(type, "parse_value", None),
|
# parse_value=getattr(type, "parse_value", None),
|
||||||
parse_literal=getattr(type, "parse_literal", None),
|
# parse_literal=getattr(type, "parse_literal", None),
|
||||||
)
|
# )
|
||||||
|
|
||||||
def construct_enum(self, map, type):
|
# def construct_enum(self, map, type):
|
||||||
values = OrderedDict()
|
# values = OrderedDict()
|
||||||
for name, value in type._meta.enum.__members__.items():
|
# for name, value in 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(type._meta.description):
|
||||||
description = type._meta.description(value)
|
# description = type._meta.description(value)
|
||||||
|
|
||||||
if not deprecation_reason and callable(type._meta.deprecation_reason):
|
# if not deprecation_reason and callable(type._meta.deprecation_reason):
|
||||||
deprecation_reason = type._meta.deprecation_reason(value)
|
# deprecation_reason = type._meta.deprecation_reason(value)
|
||||||
|
|
||||||
values[name] = GraphQLEnumValue(
|
# values[name] = GraphQLEnumValue(
|
||||||
name=name,
|
# name=name,
|
||||||
value=value.value,
|
# value=value.value,
|
||||||
description=description,
|
# description=description,
|
||||||
deprecation_reason=deprecation_reason,
|
# deprecation_reason=deprecation_reason,
|
||||||
)
|
# )
|
||||||
|
|
||||||
type_description = (
|
# type_description = (
|
||||||
type._meta.description(None)
|
# type._meta.description(None)
|
||||||
if callable(type._meta.description)
|
# if callable(type._meta.description)
|
||||||
else type._meta.description
|
# else type._meta.description
|
||||||
)
|
# )
|
||||||
|
|
||||||
return GrapheneEnumType(
|
# return GrapheneEnumType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
values=values,
|
# values=values,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type_description,
|
# description=type_description,
|
||||||
)
|
# )
|
||||||
|
|
||||||
def construct_objecttype(self, map, type):
|
# def construct_objecttype(self, map, type):
|
||||||
if type._meta.name in map:
|
# if type._meta.name in map:
|
||||||
_type = map[type._meta.name]
|
# _type = map[type._meta.name]
|
||||||
if isinstance(_type, GrapheneGraphQLType):
|
# if isinstance(_type, GrapheneGraphQLType):
|
||||||
assert _type.graphene_type == type, (
|
# assert _type.graphene_type == type, (
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
# "Found different types with the same name in the schema: {}, {}."
|
||||||
).format(_type.graphene_type, type)
|
# ).format(_type.graphene_type, type)
|
||||||
return _type
|
# return _type
|
||||||
|
|
||||||
def interfaces():
|
# def interfaces():
|
||||||
interfaces = []
|
# interfaces = []
|
||||||
for interface in type._meta.interfaces:
|
# for interface in type._meta.interfaces:
|
||||||
self.graphene_reducer(map, interface)
|
# self.graphene_reducer(map, interface)
|
||||||
internal_type = map[interface._meta.name]
|
# internal_type = map[interface._meta.name]
|
||||||
assert internal_type.graphene_type == interface
|
# assert internal_type.graphene_type == interface
|
||||||
interfaces.append(internal_type)
|
# interfaces.append(internal_type)
|
||||||
return interfaces
|
# return interfaces
|
||||||
|
|
||||||
if type._meta.possible_types:
|
# if 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, type._meta.possible_types
|
||||||
)
|
# )
|
||||||
else:
|
# else:
|
||||||
is_type_of = type.is_type_of
|
# is_type_of = type.is_type_of
|
||||||
|
|
||||||
return GrapheneObjectType(
|
# return GrapheneObjectType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type._meta.description,
|
# description=type._meta.description,
|
||||||
fields=partial(self.construct_fields_for_type, map, type),
|
# fields=partial(self.construct_fields_for_type, map, type),
|
||||||
is_type_of=is_type_of,
|
# is_type_of=is_type_of,
|
||||||
interfaces=interfaces,
|
# interfaces=interfaces,
|
||||||
)
|
# )
|
||||||
|
|
||||||
def construct_interface(self, map, type):
|
# def construct_interface(self, map, type):
|
||||||
if type._meta.name in map:
|
# if type._meta.name in map:
|
||||||
_type = map[type._meta.name]
|
# _type = map[type._meta.name]
|
||||||
if isinstance(_type, GrapheneInterfaceType):
|
# if isinstance(_type, GrapheneInterfaceType):
|
||||||
assert _type.graphene_type == type, (
|
# assert _type.graphene_type == type, (
|
||||||
"Found different types with the same name in the schema: {}, {}."
|
# "Found different types with the same name in the schema: {}, {}."
|
||||||
).format(_type.graphene_type, type)
|
# ).format(_type.graphene_type, type)
|
||||||
return _type
|
# return _type
|
||||||
|
|
||||||
_resolve_type = None
|
# _resolve_type = None
|
||||||
if type.resolve_type:
|
# if type.resolve_type:
|
||||||
_resolve_type = partial(
|
# _resolve_type = partial(
|
||||||
resolve_type, type.resolve_type, map, type._meta.name
|
# resolve_type, type.resolve_type, map, type._meta.name
|
||||||
)
|
# )
|
||||||
return GrapheneInterfaceType(
|
# return GrapheneInterfaceType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type._meta.description,
|
# description=type._meta.description,
|
||||||
fields=partial(self.construct_fields_for_type, map, type),
|
# fields=partial(self.construct_fields_for_type, map, type),
|
||||||
resolve_type=_resolve_type,
|
# resolve_type=_resolve_type,
|
||||||
)
|
# )
|
||||||
|
|
||||||
def construct_inputobjecttype(self, map, type):
|
# def construct_inputobjecttype(self, map, type):
|
||||||
return GrapheneInputObjectType(
|
# return GrapheneInputObjectType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type._meta.description,
|
# description=type._meta.description,
|
||||||
container_type=type._meta.container,
|
# container_type=type._meta.container,
|
||||||
fields=partial(
|
# fields=partial(
|
||||||
self.construct_fields_for_type, map, type, is_input_type=True
|
# self.construct_fields_for_type, map, type, is_input_type=True
|
||||||
),
|
# ),
|
||||||
)
|
# )
|
||||||
|
|
||||||
def construct_union(self, map, type):
|
# def construct_union(self, map, type):
|
||||||
_resolve_type = None
|
# _resolve_type = None
|
||||||
if type.resolve_type:
|
# if type.resolve_type:
|
||||||
_resolve_type = partial(
|
# _resolve_type = partial(
|
||||||
resolve_type, type.resolve_type, map, type._meta.name
|
# resolve_type, type.resolve_type, map, type._meta.name
|
||||||
)
|
# )
|
||||||
|
|
||||||
def types():
|
# def types():
|
||||||
union_types = []
|
# union_types = []
|
||||||
for objecttype in type._meta.types:
|
# for objecttype in type._meta.types:
|
||||||
self.graphene_reducer(map, objecttype)
|
# self.graphene_reducer(map, objecttype)
|
||||||
internal_type = map[objecttype._meta.name]
|
# internal_type = map[objecttype._meta.name]
|
||||||
assert internal_type.graphene_type == objecttype
|
# assert internal_type.graphene_type == objecttype
|
||||||
union_types.append(internal_type)
|
# union_types.append(internal_type)
|
||||||
return union_types
|
# return union_types
|
||||||
|
|
||||||
return GrapheneUnionType(
|
# return GrapheneUnionType(
|
||||||
graphene_type=type,
|
# graphene_type=type,
|
||||||
name=type._meta.name,
|
# name=type._meta.name,
|
||||||
description=type._meta.description,
|
# description=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):
|
||||||
if self.auto_camelcase:
|
# if self.auto_camelcase:
|
||||||
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 construct_fields_for_type(self, map, type, is_input_type=False):
|
||||||
fields = OrderedDict()
|
# fields = OrderedDict()
|
||||||
for name, field in type._meta.fields.items():
|
# for name, field in type._meta.fields.items():
|
||||||
if isinstance(field, Dynamic):
|
# if isinstance(field, Dynamic):
|
||||||
field = get_field_as(field.get_type(self.schema), _as=Field)
|
# field = get_field_as(field.get_type(self.schema), _as=Field)
|
||||||
if not field:
|
# if not field:
|
||||||
continue
|
# continue
|
||||||
map = self.reducer(map, field.type)
|
# map = self.reducer(map, field.type)
|
||||||
field_type = self.get_field_type(map, field.type)
|
# field_type = self.get_field_type(map, field.type)
|
||||||
if is_input_type:
|
# if is_input_type:
|
||||||
_field = GraphQLInputObjectField(
|
# _field = GraphQLInputField(
|
||||||
field_type,
|
# field_type,
|
||||||
default_value=field.default_value,
|
# default_value=field.default_value,
|
||||||
out_name=name,
|
# out_name=name,
|
||||||
description=field.description,
|
# description=field.description,
|
||||||
)
|
# )
|
||||||
else:
|
# else:
|
||||||
args = OrderedDict()
|
# args = OrderedDict()
|
||||||
for arg_name, arg in field.args.items():
|
# for arg_name, arg in field.args.items():
|
||||||
map = self.reducer(map, arg.type)
|
# map = self.reducer(map, arg.type)
|
||||||
arg_type = self.get_field_type(map, 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,
|
||||||
out_name=arg_name,
|
# out_name=arg_name,
|
||||||
description=arg.description,
|
# description=arg.description,
|
||||||
default_value=arg.default_value,
|
# default_value=arg.default_value,
|
||||||
)
|
# )
|
||||||
_field = GraphQLField(
|
# _field = GraphQLField(
|
||||||
field_type,
|
# field_type,
|
||||||
args=args,
|
# args=args,
|
||||||
resolver=field.get_resolver(
|
# resolver=field.get_resolver(
|
||||||
self.get_resolver_for_type(type, name, field.default_value)
|
# 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,
|
||||||
)
|
# )
|
||||||
field_name = field.name or self.get_name(name)
|
# field_name = field.name or self.get_name(name)
|
||||||
fields[field_name] = _field
|
# fields[field_name] = _field
|
||||||
return fields
|
# return fields
|
||||||
|
|
||||||
def get_resolver_for_type(self, type, name, default_value):
|
# def get_resolver_for_type(self, type, name, default_value):
|
||||||
if not issubclass(type, ObjectType):
|
# if not issubclass(type, ObjectType):
|
||||||
return
|
# return
|
||||||
resolver = getattr(type, "resolve_{}".format(name), None)
|
# resolver = getattr(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 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)
|
||||||
if interface_resolver:
|
# if interface_resolver:
|
||||||
break
|
# break
|
||||||
resolver = interface_resolver
|
# resolver = interface_resolver
|
||||||
|
|
||||||
# Only if is not decorated with classmethod
|
# # Only if is not decorated with classmethod
|
||||||
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 = 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):
|
# def get_field_type(self, map, type):
|
||||||
if isinstance(type, List):
|
# if isinstance(type, List):
|
||||||
return GraphQLList(self.get_field_type(map, type.of_type))
|
# return GraphQLList(self.get_field_type(map, type.of_type))
|
||||||
if isinstance(type, NonNull):
|
# if isinstance(type, NonNull):
|
||||||
return GraphQLNonNull(self.get_field_type(map, type.of_type))
|
# return GraphQLNonNull(self.get_field_type(map, type.of_type))
|
||||||
return map.get(type._meta.name)
|
# return map.get(type._meta.name)
|
||||||
|
|
|
@ -0,0 +1,7 @@
|
||||||
|
from .helpers import base64, unbase64, is_str
|
||||||
|
|
||||||
|
__all__ = [
|
||||||
|
"base64",
|
||||||
|
"unbase64",
|
||||||
|
"is_str"
|
||||||
|
]
|
13
graphene/utils/helpers.py
Normal file
13
graphene/utils/helpers.py
Normal file
|
@ -0,0 +1,13 @@
|
||||||
|
from base64 import b64encode as _base64, b64decode as _unbase64
|
||||||
|
|
||||||
|
|
||||||
|
def base64(s):
|
||||||
|
return _base64(s.encode('utf-8')).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def unbase64(s):
|
||||||
|
return _unbase64(s).decode('utf-8')
|
||||||
|
|
||||||
|
|
||||||
|
def is_str(s):
|
||||||
|
return isinstance(s, str)
|
5
setup.py
5
setup.py
|
@ -73,8 +73,6 @@ setup(
|
||||||
"Development Status :: 3 - Alpha",
|
"Development Status :: 3 - Alpha",
|
||||||
"Intended Audience :: Developers",
|
"Intended Audience :: Developers",
|
||||||
"Topic :: Software Development :: Libraries",
|
"Topic :: Software Development :: Libraries",
|
||||||
"Programming Language :: Python :: 2",
|
|
||||||
"Programming Language :: Python :: 2.7",
|
|
||||||
"Programming Language :: Python :: 3",
|
"Programming Language :: Python :: 3",
|
||||||
"Programming Language :: Python :: 3.3",
|
"Programming Language :: Python :: 3.3",
|
||||||
"Programming Language :: Python :: 3.4",
|
"Programming Language :: Python :: 3.4",
|
||||||
|
@ -86,8 +84,7 @@ setup(
|
||||||
packages=find_packages(exclude=["tests", "tests.*", "examples"]),
|
packages=find_packages(exclude=["tests", "tests.*", "examples"]),
|
||||||
install_requires=[
|
install_requires=[
|
||||||
"six>=1.10.0,<2",
|
"six>=1.10.0,<2",
|
||||||
"graphql-core>=2.1,<3",
|
"graphql-core-next==1.0.3",
|
||||||
"graphql-relay>=0.4.5,<1",
|
|
||||||
"aniso8601>=3,<4",
|
"aniso8601>=3,<4",
|
||||||
],
|
],
|
||||||
tests_require=tests_require,
|
tests_require=tests_require,
|
||||||
|
|
4
tox.ini
4
tox.ini
|
@ -1,5 +1,5 @@
|
||||||
[tox]
|
[tox]
|
||||||
envlist = flake8,py27,py34,py35,py36,py37,pre-commit,pypy,mypy
|
envlist = flake8,py34,py35,py36,py37,pre-commit,pypy,mypy
|
||||||
skipsdist = true
|
skipsdist = true
|
||||||
|
|
||||||
[testenv]
|
[testenv]
|
||||||
|
@ -9,7 +9,7 @@ deps =
|
||||||
setenv =
|
setenv =
|
||||||
PYTHONPATH = .:{envdir}
|
PYTHONPATH = .:{envdir}
|
||||||
commands =
|
commands =
|
||||||
py{27,34,py}: py.test --cov=graphene graphene examples {posargs}
|
py{34,py}: py.test --cov=graphene graphene examples {posargs}
|
||||||
py{35,36,37}: py.test --cov=graphene graphene examples tests_asyncio {posargs}
|
py{35,36,37}: py.test --cov=graphene graphene examples tests_asyncio {posargs}
|
||||||
|
|
||||||
[testenv:pre-commit]
|
[testenv:pre-commit]
|
||||||
|
|
Loading…
Reference in New Issue
Block a user