mirror of
https://github.com/graphql-python/graphene.git
synced 2025-09-21 11:22: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 &&\
|
||||
make html &&\
|
||||
cd -
|
||||
|
||||
|
||||
dev-setup:
|
||||
pip install -e ".[test]"
|
||||
|
||||
tests:
|
||||
py.test graphene
|
|
@ -28,7 +28,7 @@ from .types import (
|
|||
Dynamic,
|
||||
Union,
|
||||
Context,
|
||||
ResolveInfo,
|
||||
GraphQLResolveInfo,
|
||||
)
|
||||
from .relay import (
|
||||
Node,
|
||||
|
@ -84,7 +84,7 @@ __all__ = [
|
|||
"PageInfo",
|
||||
"lazy_import",
|
||||
"Context",
|
||||
"ResolveInfo",
|
||||
"GraphQLResolveInfo",
|
||||
# Deprecated
|
||||
"AbstractType",
|
||||
]
|
||||
|
|
|
@ -2,8 +2,6 @@ from __future__ import absolute_import
|
|||
|
||||
import six
|
||||
|
||||
from graphql.pyutils.compat import Enum
|
||||
|
||||
try:
|
||||
from inspect import signature
|
||||
except ImportError:
|
||||
|
|
|
@ -2,14 +2,155 @@ import re
|
|||
from collections import Iterable, OrderedDict
|
||||
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.field import Field
|
||||
from ..types.objecttype import ObjectType, ObjectTypeOptions
|
||||
from ..utils.thenables import maybe_thenable
|
||||
from ..utils import base64, is_str, unbase64
|
||||
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 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 inspect import isclass
|
||||
|
||||
from graphql_relay import from_global_id, to_global_id
|
||||
|
||||
from ..types import ID, Field, Interface, ObjectType
|
||||
from ..types.interface import InterfaceOptions
|
||||
from ..types.utils import get_type
|
||||
|
||||
from .utils import base64, unbase64
|
||||
|
||||
|
||||
def is_node(objecttype):
|
||||
"""
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from graphql_relay.utils import base64
|
||||
from ..utils import base64
|
||||
from promise import Promise
|
||||
|
||||
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.definitions import GrapheneObjectType
|
||||
|
|
|
@ -1,6 +1,6 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from graphql_relay import to_global_id
|
||||
from ..utils import to_global_id
|
||||
|
||||
from ...types import ObjectType, Schema, String
|
||||
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
|
||||
from graphql import ResolveInfo
|
||||
from graphql import GraphQLResolveInfo
|
||||
|
||||
from .objecttype import ObjectType
|
||||
from .interface import Interface
|
||||
|
@ -51,7 +51,7 @@ __all__ = [
|
|||
"Dynamic",
|
||||
"Union",
|
||||
"Context",
|
||||
"ResolveInfo",
|
||||
"GraphQLResolveInfo",
|
||||
# Deprecated
|
||||
"AbstractType",
|
||||
]
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from collections import OrderedDict
|
||||
|
||||
from enum import Enum
|
||||
|
||||
import six
|
||||
|
||||
from graphene.utils.subclass_with_meta import SubclassWithMeta_Meta
|
||||
|
||||
from ..pyutils.compat import Enum as PyEnum
|
||||
from .base import BaseOptions, BaseType
|
||||
from .unmountedtype import UnmountedType
|
||||
|
||||
|
@ -15,8 +16,6 @@ def eq_enum(self, other):
|
|||
return self.value is other
|
||||
|
||||
|
||||
EnumType = type(PyEnum)
|
||||
|
||||
|
||||
class EnumOptions(BaseOptions):
|
||||
enum = None # type: Enum
|
||||
|
@ -29,7 +28,7 @@ class EnumMeta(SubclassWithMeta_Meta):
|
|||
# We remove the Meta attribute from the class to not collide
|
||||
# with the enum values.
|
||||
enum_members.pop("Meta", None)
|
||||
enum = PyEnum(cls.__name__, enum_members)
|
||||
enum = Enum(cls.__name__, enum_members)
|
||||
return SubclassWithMeta_Meta.__new__(
|
||||
cls, name, bases, OrderedDict(classdict, __enum__=enum), **options
|
||||
)
|
||||
|
@ -46,7 +45,8 @@ class EnumMeta(SubclassWithMeta_Meta):
|
|||
def __call__(cls, *args, **kwargs): # noqa: N805
|
||||
if cls is Enum:
|
||||
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 cls._meta.enum(*args, **kwargs)
|
||||
|
||||
|
|
|
@ -1,12 +1,12 @@
|
|||
from __future__ import unicode_literals
|
||||
|
||||
from graphql.language.ast import (
|
||||
BooleanValue,
|
||||
FloatValue,
|
||||
IntValue,
|
||||
ListValue,
|
||||
ObjectValue,
|
||||
StringValue,
|
||||
BooleanValueNode,
|
||||
FloatValueNode,
|
||||
IntValueNode,
|
||||
ListValueNode,
|
||||
ObjectValueNode,
|
||||
StringValueNode,
|
||||
)
|
||||
|
||||
from graphene.types.scalars import MAX_INT, MIN_INT
|
||||
|
@ -30,15 +30,15 @@ class GenericScalar(Scalar):
|
|||
|
||||
@staticmethod
|
||||
def parse_literal(ast):
|
||||
if isinstance(ast, (StringValue, BooleanValue)):
|
||||
if isinstance(ast, (StringValueNode, BooleanValueNode)):
|
||||
return ast.value
|
||||
elif isinstance(ast, IntValue):
|
||||
elif isinstance(ast, IntValueNode):
|
||||
num = int(ast.value)
|
||||
if MIN_INT <= num <= MAX_INT:
|
||||
return num
|
||||
elif isinstance(ast, FloatValue):
|
||||
elif isinstance(ast, FloatValueNode):
|
||||
return float(ast.value)
|
||||
elif isinstance(ast, ListValue):
|
||||
elif isinstance(ast, ListValueNode):
|
||||
return [GenericScalar.parse_literal(value) for value in ast.values]
|
||||
elif isinstance(ast, ObjectValue):
|
||||
return {
|
||||
|
|
|
@ -1,5 +1,10 @@
|
|||
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 .unmountedtype import UnmountedType
|
||||
|
@ -99,7 +104,7 @@ class Float(Scalar):
|
|||
|
||||
@staticmethod
|
||||
def parse_literal(ast):
|
||||
if isinstance(ast, (FloatValue, IntValue)):
|
||||
if isinstance(ast, (FloatValueNode, IntValueNode)):
|
||||
return float(ast.value)
|
||||
|
||||
|
||||
|
@ -121,7 +126,7 @@ class String(Scalar):
|
|||
|
||||
@staticmethod
|
||||
def parse_literal(ast):
|
||||
if isinstance(ast, StringValue):
|
||||
if isinstance(ast, StringValueNode):
|
||||
return ast.value
|
||||
|
||||
|
||||
|
@ -135,7 +140,7 @@ class Boolean(Scalar):
|
|||
|
||||
@staticmethod
|
||||
def parse_literal(ast):
|
||||
if isinstance(ast, BooleanValue):
|
||||
if isinstance(ast, BooleanValueNode):
|
||||
return ast.value
|
||||
|
||||
|
||||
|
|
|
@ -6,13 +6,13 @@ from graphql.type.directives import (
|
|||
GraphQLIncludeDirective,
|
||||
GraphQLSkipDirective,
|
||||
)
|
||||
from graphql.type.introspection import IntrospectionSchema
|
||||
from graphql.utils.introspection_query import introspection_query
|
||||
from graphql.utils.schema_printer import print_schema
|
||||
from graphql.type.introspection import introspection_types
|
||||
from graphql.utilities.introspection_query import get_introspection_query
|
||||
from graphql.utilities.schema_printer import print_schema
|
||||
|
||||
from .definitions import GrapheneGraphQLType
|
||||
from .objecttype import ObjectType
|
||||
from .typemap import TypeMap, is_graphene_type
|
||||
from .typemap import is_graphene_type
|
||||
|
||||
|
||||
def assert_valid_root_type(_type):
|
||||
|
@ -25,103 +25,5 @@ def assert_valid_root_type(_type):
|
|||
).format(_type)
|
||||
|
||||
|
||||
class Schema(GraphQLSchema):
|
||||
"""
|
||||
Schema Definition
|
||||
Schema = GraphQLSchema
|
||||
|
||||
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
|
||||
# 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)
|
||||
print(result.errors[0])
|
||||
assert result.data is None
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import six
|
||||
|
||||
from ..argument import Argument
|
||||
from ..enum import Enum, PyEnum
|
||||
from ..enum import Enum
|
||||
from ..field import Field
|
||||
from ..inputfield import InputField
|
||||
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"]
|
||||
|
||||
|
||||
def test_enum_from_builtin_enum():
|
||||
PyRGB = PyEnum("RGB", "RED,GREEN,BLUE")
|
||||
|
||||
RGB = Enum.from_enum(PyRGB)
|
||||
assert RGB._meta.enum == PyRGB
|
||||
assert RGB.RED
|
||||
assert RGB.GREEN
|
||||
assert RGB.BLUE
|
||||
# def test_enum_from_builtin_enum_accepts_lambda_description():
|
||||
# def custom_description(value):
|
||||
# if not value:
|
||||
# return "StarWars Episodes"
|
||||
|
||||
# return "New Hope Episode" if value == Episode.NEWHOPE else "Other"
|
||||
|
||||
def test_enum_from_builtin_enum_accepts_lambda_description():
|
||||
def custom_description(value):
|
||||
if not value:
|
||||
return "StarWars Episodes"
|
||||
# def custom_deprecation_reason(value):
|
||||
# return "meh" if value == Episode.NEWHOPE else None
|
||||
|
||||
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):
|
||||
return "meh" if value == Episode.NEWHOPE else None
|
||||
# class Query(ObjectType):
|
||||
# foo = Episode()
|
||||
|
||||
PyEpisode = PyEnum("PyEpisode", "NEWHOPE,EMPIRE,JEDI")
|
||||
Episode = Enum.from_enum(
|
||||
PyEpisode,
|
||||
description=custom_description,
|
||||
deprecation_reason=custom_deprecation_reason,
|
||||
)
|
||||
# schema = Schema(query=Query)
|
||||
|
||||
class Query(ObjectType):
|
||||
foo = Episode()
|
||||
# GraphQLPyEpisode = schema._type_map["PyEpisode"].values
|
||||
|
||||
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 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"
|
||||
)
|
||||
|
||||
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
|
||||
# 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_value_from_class():
|
||||
|
|
|
@ -1,7 +1,7 @@
|
|||
import json
|
||||
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 ..dynamic import Dynamic
|
||||
|
@ -455,7 +455,7 @@ def test_query_annotated_resolvers():
|
|||
return "{}-{}".format(self, info.context.key)
|
||||
|
||||
def resolve_info(self, info):
|
||||
assert isinstance(info, ResolveInfo)
|
||||
assert isinstance(info, GraphQLResolveInfo)
|
||||
return "{}-{}".format(self, info.field_name)
|
||||
|
||||
test_schema = Schema(Query)
|
||||
|
|
|
@ -1,286 +1,286 @@
|
|||
import pytest
|
||||
from graphql.type import (
|
||||
GraphQLArgument,
|
||||
GraphQLEnumType,
|
||||
GraphQLEnumValue,
|
||||
GraphQLField,
|
||||
GraphQLInputObjectField,
|
||||
GraphQLInputObjectType,
|
||||
GraphQLInterfaceType,
|
||||
GraphQLObjectType,
|
||||
GraphQLString,
|
||||
)
|
||||
# import pytest
|
||||
# from graphql.type import (
|
||||
# GraphQLArgument,
|
||||
# GraphQLEnumType,
|
||||
# GraphQLEnumValue,
|
||||
# GraphQLField,
|
||||
# GraphQLInputField,
|
||||
# GraphQLInputObjectType,
|
||||
# GraphQLInterfaceType,
|
||||
# GraphQLObjectType,
|
||||
# GraphQLString,
|
||||
# )
|
||||
|
||||
from ..dynamic import Dynamic
|
||||
from ..enum import Enum
|
||||
from ..field import Field
|
||||
from ..inputfield import InputField
|
||||
from ..inputobjecttype import InputObjectType
|
||||
from ..interface import Interface
|
||||
from ..objecttype import ObjectType
|
||||
from ..scalars import Int, String
|
||||
from ..structures import List, NonNull
|
||||
from ..typemap import TypeMap, resolve_type
|
||||
# from ..dynamic import Dynamic
|
||||
# from ..enum import Enum
|
||||
# from ..field import Field
|
||||
# from ..inputfield import InputField
|
||||
# from ..inputobjecttype import InputObjectType
|
||||
# from ..interface import Interface
|
||||
# from ..objecttype import ObjectType
|
||||
# from ..scalars import Int, String
|
||||
# from ..structures import List, NonNull
|
||||
# from ..typemap import resolve_type
|
||||
|
||||
|
||||
def test_enum():
|
||||
class MyEnum(Enum):
|
||||
"""Description"""
|
||||
# def test_enum():
|
||||
# class MyEnum(Enum):
|
||||
# """Description"""
|
||||
|
||||
foo = 1
|
||||
bar = 2
|
||||
# foo = 1
|
||||
# bar = 2
|
||||
|
||||
@property
|
||||
def description(self):
|
||||
return "Description {}={}".format(self.name, self.value)
|
||||
# @property
|
||||
# def description(self):
|
||||
# return "Description {}={}".format(self.name, self.value)
|
||||
|
||||
@property
|
||||
def deprecation_reason(self):
|
||||
if self == MyEnum.foo:
|
||||
return "Is deprecated"
|
||||
# @property
|
||||
# def deprecation_reason(self):
|
||||
# if self == MyEnum.foo:
|
||||
# return "Is deprecated"
|
||||
|
||||
typemap = TypeMap([MyEnum])
|
||||
assert "MyEnum" in typemap
|
||||
graphql_enum = typemap["MyEnum"]
|
||||
assert isinstance(graphql_enum, GraphQLEnumType)
|
||||
assert graphql_enum.name == "MyEnum"
|
||||
assert graphql_enum.description == "Description"
|
||||
values = graphql_enum.values
|
||||
assert values == [
|
||||
GraphQLEnumValue(
|
||||
name="foo",
|
||||
value=1,
|
||||
description="Description foo=1",
|
||||
deprecation_reason="Is deprecated",
|
||||
),
|
||||
GraphQLEnumValue(name="bar", value=2, description="Description bar=2"),
|
||||
]
|
||||
# typemap = TypeMap([MyEnum])
|
||||
# assert "MyEnum" in typemap
|
||||
# graphql_enum = typemap["MyEnum"]
|
||||
# assert isinstance(graphql_enum, GraphQLEnumType)
|
||||
# assert graphql_enum.name == "MyEnum"
|
||||
# assert graphql_enum.description == "Description"
|
||||
# values = graphql_enum.values
|
||||
# assert values == [
|
||||
# GraphQLEnumValue(
|
||||
# name="foo",
|
||||
# value=1,
|
||||
# description="Description foo=1",
|
||||
# deprecation_reason="Is deprecated",
|
||||
# ),
|
||||
# GraphQLEnumValue(name="bar", value=2, description="Description bar=2"),
|
||||
# ]
|
||||
|
||||
|
||||
def test_objecttype():
|
||||
class MyObjectType(ObjectType):
|
||||
"""Description"""
|
||||
# def test_objecttype():
|
||||
# class MyObjectType(ObjectType):
|
||||
# """Description"""
|
||||
|
||||
foo = String(
|
||||
bar=String(description="Argument description", default_value="x"),
|
||||
description="Field description",
|
||||
)
|
||||
bar = String(name="gizmo")
|
||||
# foo = String(
|
||||
# bar=String(description="Argument description", default_value="x"),
|
||||
# description="Field description",
|
||||
# )
|
||||
# bar = String(name="gizmo")
|
||||
|
||||
def resolve_foo(self, bar):
|
||||
return bar
|
||||
# def resolve_foo(self, bar):
|
||||
# return bar
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
assert "MyObjectType" in typemap
|
||||
graphql_type = typemap["MyObjectType"]
|
||||
assert isinstance(graphql_type, GraphQLObjectType)
|
||||
assert graphql_type.name == "MyObjectType"
|
||||
assert graphql_type.description == "Description"
|
||||
# typemap = TypeMap([MyObjectType])
|
||||
# assert "MyObjectType" in typemap
|
||||
# graphql_type = typemap["MyObjectType"]
|
||||
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||
# assert graphql_type.name == "MyObjectType"
|
||||
# assert graphql_type.description == "Description"
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["foo", "gizmo"]
|
||||
foo_field = fields["foo"]
|
||||
assert isinstance(foo_field, GraphQLField)
|
||||
assert foo_field.description == "Field description"
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["foo", "gizmo"]
|
||||
# foo_field = fields["foo"]
|
||||
# assert isinstance(foo_field, GraphQLField)
|
||||
# assert foo_field.description == "Field description"
|
||||
|
||||
assert foo_field.args == {
|
||||
"bar": GraphQLArgument(
|
||||
GraphQLString,
|
||||
description="Argument description",
|
||||
default_value="x",
|
||||
out_name="bar",
|
||||
)
|
||||
}
|
||||
# assert foo_field.args == {
|
||||
# "bar": GraphQLArgument(
|
||||
# GraphQLString,
|
||||
# description="Argument description",
|
||||
# default_value="x",
|
||||
# out_name="bar",
|
||||
# )
|
||||
# }
|
||||
|
||||
|
||||
def test_dynamic_objecttype():
|
||||
class MyObjectType(ObjectType):
|
||||
"""Description"""
|
||||
# def test_dynamic_objecttype():
|
||||
# class MyObjectType(ObjectType):
|
||||
# """Description"""
|
||||
|
||||
bar = Dynamic(lambda: Field(String))
|
||||
own = Field(lambda: MyObjectType)
|
||||
# bar = Dynamic(lambda: Field(String))
|
||||
# own = Field(lambda: MyObjectType)
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
assert "MyObjectType" in typemap
|
||||
assert list(MyObjectType._meta.fields.keys()) == ["bar", "own"]
|
||||
graphql_type = typemap["MyObjectType"]
|
||||
# typemap = TypeMap([MyObjectType])
|
||||
# assert "MyObjectType" in typemap
|
||||
# assert list(MyObjectType._meta.fields.keys()) == ["bar", "own"]
|
||||
# graphql_type = typemap["MyObjectType"]
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["bar", "own"]
|
||||
assert fields["bar"].type == GraphQLString
|
||||
assert fields["own"].type == graphql_type
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["bar", "own"]
|
||||
# assert fields["bar"].type == GraphQLString
|
||||
# assert fields["own"].type == graphql_type
|
||||
|
||||
|
||||
def test_interface():
|
||||
class MyInterface(Interface):
|
||||
"""Description"""
|
||||
# def test_interface():
|
||||
# class MyInterface(Interface):
|
||||
# """Description"""
|
||||
|
||||
foo = String(
|
||||
bar=String(description="Argument description", default_value="x"),
|
||||
description="Field description",
|
||||
)
|
||||
bar = String(name="gizmo", first_arg=String(), other_arg=String(name="oth_arg"))
|
||||
own = Field(lambda: MyInterface)
|
||||
# foo = String(
|
||||
# bar=String(description="Argument description", default_value="x"),
|
||||
# description="Field description",
|
||||
# )
|
||||
# bar = String(name="gizmo", first_arg=String(), other_arg=String(name="oth_arg"))
|
||||
# own = Field(lambda: MyInterface)
|
||||
|
||||
def resolve_foo(self, args, info):
|
||||
return args.get("bar")
|
||||
# def resolve_foo(self, args, info):
|
||||
# return args.get("bar")
|
||||
|
||||
typemap = TypeMap([MyInterface])
|
||||
assert "MyInterface" in typemap
|
||||
graphql_type = typemap["MyInterface"]
|
||||
assert isinstance(graphql_type, GraphQLInterfaceType)
|
||||
assert graphql_type.name == "MyInterface"
|
||||
assert graphql_type.description == "Description"
|
||||
# typemap = TypeMap([MyInterface])
|
||||
# assert "MyInterface" in typemap
|
||||
# graphql_type = typemap["MyInterface"]
|
||||
# assert isinstance(graphql_type, GraphQLInterfaceType)
|
||||
# assert graphql_type.name == "MyInterface"
|
||||
# assert graphql_type.description == "Description"
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["foo", "gizmo", "own"]
|
||||
assert fields["own"].type == graphql_type
|
||||
assert list(fields["gizmo"].args.keys()) == ["firstArg", "oth_arg"]
|
||||
foo_field = fields["foo"]
|
||||
assert isinstance(foo_field, GraphQLField)
|
||||
assert foo_field.description == "Field description"
|
||||
assert not foo_field.resolver # Resolver not attached in interfaces
|
||||
assert foo_field.args == {
|
||||
"bar": GraphQLArgument(
|
||||
GraphQLString,
|
||||
description="Argument description",
|
||||
default_value="x",
|
||||
out_name="bar",
|
||||
)
|
||||
}
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["foo", "gizmo", "own"]
|
||||
# assert fields["own"].type == graphql_type
|
||||
# assert list(fields["gizmo"].args.keys()) == ["firstArg", "oth_arg"]
|
||||
# foo_field = fields["foo"]
|
||||
# assert isinstance(foo_field, GraphQLField)
|
||||
# assert foo_field.description == "Field description"
|
||||
# assert not foo_field.resolver # Resolver not attached in interfaces
|
||||
# assert foo_field.args == {
|
||||
# "bar": GraphQLArgument(
|
||||
# GraphQLString,
|
||||
# description="Argument description",
|
||||
# default_value="x",
|
||||
# out_name="bar",
|
||||
# )
|
||||
# }
|
||||
|
||||
|
||||
def test_inputobject():
|
||||
class OtherObjectType(InputObjectType):
|
||||
thingy = NonNull(Int)
|
||||
# def test_inputobject():
|
||||
# class OtherObjectType(InputObjectType):
|
||||
# thingy = NonNull(Int)
|
||||
|
||||
class MyInnerObjectType(InputObjectType):
|
||||
some_field = String()
|
||||
some_other_field = List(OtherObjectType)
|
||||
# class MyInnerObjectType(InputObjectType):
|
||||
# some_field = String()
|
||||
# some_other_field = List(OtherObjectType)
|
||||
|
||||
class MyInputObjectType(InputObjectType):
|
||||
"""Description"""
|
||||
# class MyInputObjectType(InputObjectType):
|
||||
# """Description"""
|
||||
|
||||
foo_bar = String(description="Field description")
|
||||
bar = String(name="gizmo")
|
||||
baz = NonNull(MyInnerObjectType)
|
||||
own = InputField(lambda: MyInputObjectType)
|
||||
# foo_bar = String(description="Field description")
|
||||
# bar = String(name="gizmo")
|
||||
# baz = NonNull(MyInnerObjectType)
|
||||
# own = InputField(lambda: MyInputObjectType)
|
||||
|
||||
def resolve_foo_bar(self, args, info):
|
||||
return args.get("bar")
|
||||
# def resolve_foo_bar(self, args, info):
|
||||
# return args.get("bar")
|
||||
|
||||
typemap = TypeMap([MyInputObjectType])
|
||||
assert "MyInputObjectType" in typemap
|
||||
graphql_type = typemap["MyInputObjectType"]
|
||||
assert isinstance(graphql_type, GraphQLInputObjectType)
|
||||
assert graphql_type.name == "MyInputObjectType"
|
||||
assert graphql_type.description == "Description"
|
||||
# typemap = TypeMap([MyInputObjectType])
|
||||
# assert "MyInputObjectType" in typemap
|
||||
# graphql_type = typemap["MyInputObjectType"]
|
||||
# assert isinstance(graphql_type, GraphQLInputObjectType)
|
||||
# assert graphql_type.name == "MyInputObjectType"
|
||||
# assert graphql_type.description == "Description"
|
||||
|
||||
other_graphql_type = typemap["OtherObjectType"]
|
||||
inner_graphql_type = typemap["MyInnerObjectType"]
|
||||
container = graphql_type.create_container(
|
||||
{
|
||||
"bar": "oh!",
|
||||
"baz": inner_graphql_type.create_container(
|
||||
{
|
||||
"some_other_field": [
|
||||
other_graphql_type.create_container({"thingy": 1}),
|
||||
other_graphql_type.create_container({"thingy": 2}),
|
||||
]
|
||||
}
|
||||
),
|
||||
}
|
||||
)
|
||||
assert isinstance(container, MyInputObjectType)
|
||||
assert "bar" in container
|
||||
assert container.bar == "oh!"
|
||||
assert "foo_bar" not in container
|
||||
assert container.foo_bar is None
|
||||
assert container.baz.some_field is None
|
||||
assert container.baz.some_other_field[0].thingy == 1
|
||||
assert container.baz.some_other_field[1].thingy == 2
|
||||
# other_graphql_type = typemap["OtherObjectType"]
|
||||
# inner_graphql_type = typemap["MyInnerObjectType"]
|
||||
# container = graphql_type.create_container(
|
||||
# {
|
||||
# "bar": "oh!",
|
||||
# "baz": inner_graphql_type.create_container(
|
||||
# {
|
||||
# "some_other_field": [
|
||||
# other_graphql_type.create_container({"thingy": 1}),
|
||||
# other_graphql_type.create_container({"thingy": 2}),
|
||||
# ]
|
||||
# }
|
||||
# ),
|
||||
# }
|
||||
# )
|
||||
# assert isinstance(container, MyInputObjectType)
|
||||
# assert "bar" in container
|
||||
# assert container.bar == "oh!"
|
||||
# assert "foo_bar" not in container
|
||||
# assert container.foo_bar is None
|
||||
# assert container.baz.some_field is None
|
||||
# assert container.baz.some_other_field[0].thingy == 1
|
||||
# assert container.baz.some_other_field[1].thingy == 2
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["fooBar", "gizmo", "baz", "own"]
|
||||
own_field = fields["own"]
|
||||
assert own_field.type == graphql_type
|
||||
foo_field = fields["fooBar"]
|
||||
assert isinstance(foo_field, GraphQLInputObjectField)
|
||||
assert foo_field.description == "Field description"
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["fooBar", "gizmo", "baz", "own"]
|
||||
# own_field = fields["own"]
|
||||
# assert own_field.type == graphql_type
|
||||
# foo_field = fields["fooBar"]
|
||||
# assert isinstance(foo_field, GraphQLInputObjectField)
|
||||
# assert foo_field.description == "Field description"
|
||||
|
||||
|
||||
def test_objecttype_camelcase():
|
||||
class MyObjectType(ObjectType):
|
||||
"""Description"""
|
||||
# def test_objecttype_camelcase():
|
||||
# class MyObjectType(ObjectType):
|
||||
# """Description"""
|
||||
|
||||
foo_bar = String(bar_foo=String())
|
||||
# foo_bar = String(bar_foo=String())
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
assert "MyObjectType" in typemap
|
||||
graphql_type = typemap["MyObjectType"]
|
||||
assert isinstance(graphql_type, GraphQLObjectType)
|
||||
assert graphql_type.name == "MyObjectType"
|
||||
assert graphql_type.description == "Description"
|
||||
# typemap = TypeMap([MyObjectType])
|
||||
# assert "MyObjectType" in typemap
|
||||
# graphql_type = typemap["MyObjectType"]
|
||||
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||
# assert graphql_type.name == "MyObjectType"
|
||||
# assert graphql_type.description == "Description"
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["fooBar"]
|
||||
foo_field = fields["fooBar"]
|
||||
assert isinstance(foo_field, GraphQLField)
|
||||
assert foo_field.args == {
|
||||
"barFoo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||
}
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["fooBar"]
|
||||
# foo_field = fields["fooBar"]
|
||||
# assert isinstance(foo_field, GraphQLField)
|
||||
# assert foo_field.args == {
|
||||
# "barFoo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||
# }
|
||||
|
||||
|
||||
def test_objecttype_camelcase_disabled():
|
||||
class MyObjectType(ObjectType):
|
||||
"""Description"""
|
||||
# def test_objecttype_camelcase_disabled():
|
||||
# class MyObjectType(ObjectType):
|
||||
# """Description"""
|
||||
|
||||
foo_bar = String(bar_foo=String())
|
||||
# foo_bar = String(bar_foo=String())
|
||||
|
||||
typemap = TypeMap([MyObjectType], auto_camelcase=False)
|
||||
assert "MyObjectType" in typemap
|
||||
graphql_type = typemap["MyObjectType"]
|
||||
assert isinstance(graphql_type, GraphQLObjectType)
|
||||
assert graphql_type.name == "MyObjectType"
|
||||
assert graphql_type.description == "Description"
|
||||
# typemap = TypeMap([MyObjectType], auto_camelcase=False)
|
||||
# assert "MyObjectType" in typemap
|
||||
# graphql_type = typemap["MyObjectType"]
|
||||
# assert isinstance(graphql_type, GraphQLObjectType)
|
||||
# assert graphql_type.name == "MyObjectType"
|
||||
# assert graphql_type.description == "Description"
|
||||
|
||||
fields = graphql_type.fields
|
||||
assert list(fields.keys()) == ["foo_bar"]
|
||||
foo_field = fields["foo_bar"]
|
||||
assert isinstance(foo_field, GraphQLField)
|
||||
assert foo_field.args == {
|
||||
"bar_foo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||
}
|
||||
# fields = graphql_type.fields
|
||||
# assert list(fields.keys()) == ["foo_bar"]
|
||||
# foo_field = fields["foo_bar"]
|
||||
# assert isinstance(foo_field, GraphQLField)
|
||||
# assert foo_field.args == {
|
||||
# "bar_foo": GraphQLArgument(GraphQLString, out_name="bar_foo")
|
||||
# }
|
||||
|
||||
|
||||
def test_objecttype_with_possible_types():
|
||||
class MyObjectType(ObjectType):
|
||||
"""Description"""
|
||||
# def test_objecttype_with_possible_types():
|
||||
# class MyObjectType(ObjectType):
|
||||
# """Description"""
|
||||
|
||||
class Meta:
|
||||
possible_types = (dict,)
|
||||
# class Meta:
|
||||
# possible_types = (dict,)
|
||||
|
||||
foo_bar = String()
|
||||
# foo_bar = String()
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
graphql_type = typemap["MyObjectType"]
|
||||
assert graphql_type.is_type_of
|
||||
assert graphql_type.is_type_of({}, None) is True
|
||||
assert graphql_type.is_type_of(MyObjectType(), None) is False
|
||||
# typemap = TypeMap([MyObjectType])
|
||||
# graphql_type = typemap["MyObjectType"]
|
||||
# assert graphql_type.is_type_of
|
||||
# assert graphql_type.is_type_of({}, None) is True
|
||||
# assert graphql_type.is_type_of(MyObjectType(), None) is False
|
||||
|
||||
|
||||
def test_resolve_type_with_missing_type():
|
||||
class MyObjectType(ObjectType):
|
||||
foo_bar = String()
|
||||
# def test_resolve_type_with_missing_type():
|
||||
# class MyObjectType(ObjectType):
|
||||
# foo_bar = String()
|
||||
|
||||
class MyOtherObjectType(ObjectType):
|
||||
fizz_buzz = String()
|
||||
# class MyOtherObjectType(ObjectType):
|
||||
# fizz_buzz = String()
|
||||
|
||||
def resolve_type_func(root, info):
|
||||
return MyOtherObjectType
|
||||
# def resolve_type_func(root, info):
|
||||
# return MyOtherObjectType
|
||||
|
||||
typemap = TypeMap([MyObjectType])
|
||||
with pytest.raises(AssertionError) as excinfo:
|
||||
resolve_type(resolve_type_func, typemap, "MyOtherObjectType", {}, {})
|
||||
# typemap = TypeMap([MyObjectType])
|
||||
# with pytest.raises(AssertionError) as excinfo:
|
||||
# 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):
|
||||
return input
|
||||
|
||||
|
||||
schema = Schema(query=Query)
|
||||
|
||||
|
||||
|
|
|
@ -8,15 +8,14 @@ from graphql import (
|
|||
GraphQLField,
|
||||
GraphQLFloat,
|
||||
GraphQLID,
|
||||
GraphQLInputObjectField,
|
||||
GraphQLInputField,
|
||||
GraphQLInt,
|
||||
GraphQLList,
|
||||
GraphQLNonNull,
|
||||
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.typemap import GraphQLTypeMap
|
||||
|
||||
from ..utils.get_unbound_function import get_unbound_function
|
||||
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:
|
||||
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):
|
||||
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)
|
||||
|
||||
|
||||
class TypeMap(GraphQLTypeMap):
|
||||
def __init__(self, types, auto_camelcase=True, schema=None):
|
||||
self.auto_camelcase = auto_camelcase
|
||||
self.schema = schema
|
||||
super(TypeMap, self).__init__(types)
|
||||
# class TypeMap(object):
|
||||
# def __init__(self, types, auto_camelcase=True, schema=None):
|
||||
# self.auto_camelcase = auto_camelcase
|
||||
# self.schema = schema
|
||||
# types = [t for t in types if t]
|
||||
# super(TypeMap, self).__init__(types)
|
||||
|
||||
def reducer(self, map, type):
|
||||
if not type:
|
||||
return map
|
||||
if inspect.isfunction(type):
|
||||
type = type()
|
||||
if is_graphene_type(type):
|
||||
return self.graphene_reducer(map, type)
|
||||
return GraphQLTypeMap.reducer(map, type)
|
||||
# def reducer(self, map, type):
|
||||
# if not type:
|
||||
# return map
|
||||
# if inspect.isfunction(type):
|
||||
# type = type()
|
||||
# if is_graphene_type(type):
|
||||
# return self.graphene_reducer(map, type)
|
||||
# return GraphQLSchema.reducer(map, type)
|
||||
|
||||
def graphene_reducer(self, map, type):
|
||||
if isinstance(type, (List, NonNull)):
|
||||
return self.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
|
||||
# def graphene_reducer(self, map, type):
|
||||
# if isinstance(type, (List, NonNull)):
|
||||
# return self.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(map, type)
|
||||
elif issubclass(type, Enum):
|
||||
internal_type = self.construct_enum(map, type)
|
||||
elif issubclass(type, Union):
|
||||
internal_type = self.construct_union(map, type)
|
||||
else:
|
||||
raise Exception("Expected Graphene type, but received: {}.".format(type))
|
||||
# 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(map, type)
|
||||
# elif issubclass(type, Enum):
|
||||
# internal_type = self.construct_enum(map, type)
|
||||
# elif issubclass(type, Union):
|
||||
# internal_type = self.construct_union(map, type)
|
||||
# else:
|
||||
# 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):
|
||||
# We have a mapping to the original GraphQL types
|
||||
# so there are no collisions.
|
||||
_scalars = {
|
||||
String: GraphQLString,
|
||||
Int: GraphQLInt,
|
||||
Float: GraphQLFloat,
|
||||
Boolean: GraphQLBoolean,
|
||||
ID: GraphQLID,
|
||||
}
|
||||
if type in _scalars:
|
||||
return _scalars[type]
|
||||
# def construct_scalar(self, map, type):
|
||||
# # We have a mapping to the original GraphQL types
|
||||
# # so there are no collisions.
|
||||
# _scalars = {
|
||||
# String: GraphQLString,
|
||||
# Int: GraphQLInt,
|
||||
# Float: GraphQLFloat,
|
||||
# Boolean: GraphQLBoolean,
|
||||
# ID: GraphQLID,
|
||||
# }
|
||||
# if type in _scalars:
|
||||
# return _scalars[type]
|
||||
|
||||
return GrapheneScalarType(
|
||||
graphene_type=type,
|
||||
name=type._meta.name,
|
||||
description=type._meta.description,
|
||||
serialize=getattr(type, "serialize", None),
|
||||
parse_value=getattr(type, "parse_value", None),
|
||||
parse_literal=getattr(type, "parse_literal", None),
|
||||
)
|
||||
# return GrapheneScalarType(
|
||||
# graphene_type=type,
|
||||
# name=type._meta.name,
|
||||
# description=type._meta.description,
|
||||
# serialize=getattr(type, "serialize", None),
|
||||
# parse_value=getattr(type, "parse_value", None),
|
||||
# parse_literal=getattr(type, "parse_literal", None),
|
||||
# )
|
||||
|
||||
def construct_enum(self, map, type):
|
||||
values = OrderedDict()
|
||||
for name, value in type._meta.enum.__members__.items():
|
||||
description = getattr(value, "description", None)
|
||||
deprecation_reason = getattr(value, "deprecation_reason", None)
|
||||
if not description and callable(type._meta.description):
|
||||
description = type._meta.description(value)
|
||||
# def construct_enum(self, map, type):
|
||||
# values = OrderedDict()
|
||||
# for name, value in type._meta.enum.__members__.items():
|
||||
# description = getattr(value, "description", None)
|
||||
# deprecation_reason = getattr(value, "deprecation_reason", None)
|
||||
# if not description and callable(type._meta.description):
|
||||
# description = type._meta.description(value)
|
||||
|
||||
if not deprecation_reason and callable(type._meta.deprecation_reason):
|
||||
deprecation_reason = type._meta.deprecation_reason(value)
|
||||
# if not deprecation_reason and callable(type._meta.deprecation_reason):
|
||||
# deprecation_reason = type._meta.deprecation_reason(value)
|
||||
|
||||
values[name] = GraphQLEnumValue(
|
||||
name=name,
|
||||
value=value.value,
|
||||
description=description,
|
||||
deprecation_reason=deprecation_reason,
|
||||
)
|
||||
# values[name] = GraphQLEnumValue(
|
||||
# name=name,
|
||||
# value=value.value,
|
||||
# description=description,
|
||||
# deprecation_reason=deprecation_reason,
|
||||
# )
|
||||
|
||||
type_description = (
|
||||
type._meta.description(None)
|
||||
if callable(type._meta.description)
|
||||
else type._meta.description
|
||||
)
|
||||
# type_description = (
|
||||
# type._meta.description(None)
|
||||
# if callable(type._meta.description)
|
||||
# else type._meta.description
|
||||
# )
|
||||
|
||||
return GrapheneEnumType(
|
||||
graphene_type=type,
|
||||
values=values,
|
||||
name=type._meta.name,
|
||||
description=type_description,
|
||||
)
|
||||
# return GrapheneEnumType(
|
||||
# graphene_type=type,
|
||||
# values=values,
|
||||
# name=type._meta.name,
|
||||
# description=type_description,
|
||||
# )
|
||||
|
||||
def construct_objecttype(self, map, 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 _type
|
||||
# def construct_objecttype(self, map, 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 _type
|
||||
|
||||
def interfaces():
|
||||
interfaces = []
|
||||
for interface in type._meta.interfaces:
|
||||
self.graphene_reducer(map, interface)
|
||||
internal_type = map[interface._meta.name]
|
||||
assert internal_type.graphene_type == interface
|
||||
interfaces.append(internal_type)
|
||||
return interfaces
|
||||
# def interfaces():
|
||||
# interfaces = []
|
||||
# for interface in type._meta.interfaces:
|
||||
# self.graphene_reducer(map, interface)
|
||||
# internal_type = map[interface._meta.name]
|
||||
# assert internal_type.graphene_type == interface
|
||||
# interfaces.append(internal_type)
|
||||
# return interfaces
|
||||
|
||||
if type._meta.possible_types:
|
||||
is_type_of = partial(
|
||||
is_type_of_from_possible_types, type._meta.possible_types
|
||||
)
|
||||
else:
|
||||
is_type_of = type.is_type_of
|
||||
# if type._meta.possible_types:
|
||||
# is_type_of = partial(
|
||||
# is_type_of_from_possible_types, type._meta.possible_types
|
||||
# )
|
||||
# else:
|
||||
# is_type_of = type.is_type_of
|
||||
|
||||
return GrapheneObjectType(
|
||||
graphene_type=type,
|
||||
name=type._meta.name,
|
||||
description=type._meta.description,
|
||||
fields=partial(self.construct_fields_for_type, map, type),
|
||||
is_type_of=is_type_of,
|
||||
interfaces=interfaces,
|
||||
)
|
||||
# return GrapheneObjectType(
|
||||
# graphene_type=type,
|
||||
# name=type._meta.name,
|
||||
# description=type._meta.description,
|
||||
# fields=partial(self.construct_fields_for_type, map, type),
|
||||
# is_type_of=is_type_of,
|
||||
# interfaces=interfaces,
|
||||
# )
|
||||
|
||||
def construct_interface(self, map, type):
|
||||
if type._meta.name in map:
|
||||
_type = map[type._meta.name]
|
||||
if isinstance(_type, GrapheneInterfaceType):
|
||||
assert _type.graphene_type == type, (
|
||||
"Found different types with the same name in the schema: {}, {}."
|
||||
).format(_type.graphene_type, type)
|
||||
return _type
|
||||
# def construct_interface(self, map, type):
|
||||
# if type._meta.name in map:
|
||||
# _type = map[type._meta.name]
|
||||
# if isinstance(_type, GrapheneInterfaceType):
|
||||
# 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(
|
||||
graphene_type=type,
|
||||
name=type._meta.name,
|
||||
description=type._meta.description,
|
||||
fields=partial(self.construct_fields_for_type, map, type),
|
||||
resolve_type=_resolve_type,
|
||||
)
|
||||
# _resolve_type = None
|
||||
# if type.resolve_type:
|
||||
# _resolve_type = partial(
|
||||
# resolve_type, type.resolve_type, map, type._meta.name
|
||||
# )
|
||||
# return GrapheneInterfaceType(
|
||||
# graphene_type=type,
|
||||
# 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 GrapheneInputObjectType(
|
||||
graphene_type=type,
|
||||
name=type._meta.name,
|
||||
description=type._meta.description,
|
||||
container_type=type._meta.container,
|
||||
fields=partial(
|
||||
self.construct_fields_for_type, map, type, is_input_type=True
|
||||
),
|
||||
)
|
||||
# def construct_inputobjecttype(self, map, type):
|
||||
# return GrapheneInputObjectType(
|
||||
# graphene_type=type,
|
||||
# name=type._meta.name,
|
||||
# description=type._meta.description,
|
||||
# container_type=type._meta.container,
|
||||
# fields=partial(
|
||||
# self.construct_fields_for_type, map, type, is_input_type=True
|
||||
# ),
|
||||
# )
|
||||
|
||||
def construct_union(self, map, type):
|
||||
_resolve_type = None
|
||||
if type.resolve_type:
|
||||
_resolve_type = partial(
|
||||
resolve_type, type.resolve_type, map, type._meta.name
|
||||
)
|
||||
# def construct_union(self, map, type):
|
||||
# _resolve_type = None
|
||||
# if type.resolve_type:
|
||||
# _resolve_type = partial(
|
||||
# resolve_type, type.resolve_type, map, type._meta.name
|
||||
# )
|
||||
|
||||
def types():
|
||||
union_types = []
|
||||
for objecttype in type._meta.types:
|
||||
self.graphene_reducer(map, objecttype)
|
||||
internal_type = map[objecttype._meta.name]
|
||||
assert internal_type.graphene_type == objecttype
|
||||
union_types.append(internal_type)
|
||||
return union_types
|
||||
# def types():
|
||||
# union_types = []
|
||||
# for objecttype in type._meta.types:
|
||||
# self.graphene_reducer(map, objecttype)
|
||||
# internal_type = map[objecttype._meta.name]
|
||||
# assert internal_type.graphene_type == objecttype
|
||||
# union_types.append(internal_type)
|
||||
# return union_types
|
||||
|
||||
return GrapheneUnionType(
|
||||
graphene_type=type,
|
||||
name=type._meta.name,
|
||||
description=type._meta.description,
|
||||
types=types,
|
||||
resolve_type=_resolve_type,
|
||||
)
|
||||
# return GrapheneUnionType(
|
||||
# graphene_type=type,
|
||||
# name=type._meta.name,
|
||||
# description=type._meta.description,
|
||||
# types=types,
|
||||
# resolve_type=_resolve_type,
|
||||
# )
|
||||
|
||||
def get_name(self, name):
|
||||
if self.auto_camelcase:
|
||||
return to_camel_case(name)
|
||||
return name
|
||||
# def get_name(self, name):
|
||||
# if self.auto_camelcase:
|
||||
# return to_camel_case(name)
|
||||
# return name
|
||||
|
||||
def construct_fields_for_type(self, map, type, is_input_type=False):
|
||||
fields = OrderedDict()
|
||||
for name, field in type._meta.fields.items():
|
||||
if isinstance(field, Dynamic):
|
||||
field = get_field_as(field.get_type(self.schema), _as=Field)
|
||||
if not field:
|
||||
continue
|
||||
map = self.reducer(map, field.type)
|
||||
field_type = self.get_field_type(map, field.type)
|
||||
if is_input_type:
|
||||
_field = GraphQLInputObjectField(
|
||||
field_type,
|
||||
default_value=field.default_value,
|
||||
out_name=name,
|
||||
description=field.description,
|
||||
)
|
||||
else:
|
||||
args = OrderedDict()
|
||||
for arg_name, arg in field.args.items():
|
||||
map = self.reducer(map, arg.type)
|
||||
arg_type = self.get_field_type(map, arg.type)
|
||||
processed_arg_name = arg.name or self.get_name(arg_name)
|
||||
args[processed_arg_name] = GraphQLArgument(
|
||||
arg_type,
|
||||
out_name=arg_name,
|
||||
description=arg.description,
|
||||
default_value=arg.default_value,
|
||||
)
|
||||
_field = GraphQLField(
|
||||
field_type,
|
||||
args=args,
|
||||
resolver=field.get_resolver(
|
||||
self.get_resolver_for_type(type, name, field.default_value)
|
||||
),
|
||||
deprecation_reason=field.deprecation_reason,
|
||||
description=field.description,
|
||||
)
|
||||
field_name = field.name or self.get_name(name)
|
||||
fields[field_name] = _field
|
||||
return fields
|
||||
# def construct_fields_for_type(self, map, type, is_input_type=False):
|
||||
# fields = OrderedDict()
|
||||
# for name, field in type._meta.fields.items():
|
||||
# if isinstance(field, Dynamic):
|
||||
# field = get_field_as(field.get_type(self.schema), _as=Field)
|
||||
# if not field:
|
||||
# continue
|
||||
# map = self.reducer(map, field.type)
|
||||
# field_type = self.get_field_type(map, field.type)
|
||||
# if is_input_type:
|
||||
# _field = GraphQLInputField(
|
||||
# field_type,
|
||||
# default_value=field.default_value,
|
||||
# out_name=name,
|
||||
# description=field.description,
|
||||
# )
|
||||
# else:
|
||||
# args = OrderedDict()
|
||||
# for arg_name, arg in field.args.items():
|
||||
# map = self.reducer(map, arg.type)
|
||||
# arg_type = self.get_field_type(map, arg.type)
|
||||
# processed_arg_name = arg.name or self.get_name(arg_name)
|
||||
# args[processed_arg_name] = GraphQLArgument(
|
||||
# arg_type,
|
||||
# out_name=arg_name,
|
||||
# description=arg.description,
|
||||
# default_value=arg.default_value,
|
||||
# )
|
||||
# _field = GraphQLField(
|
||||
# field_type,
|
||||
# args=args,
|
||||
# resolver=field.get_resolver(
|
||||
# self.get_resolver_for_type(type, name, field.default_value)
|
||||
# ),
|
||||
# deprecation_reason=field.deprecation_reason,
|
||||
# description=field.description,
|
||||
# )
|
||||
# field_name = field.name or self.get_name(name)
|
||||
# fields[field_name] = _field
|
||||
# return fields
|
||||
|
||||
def get_resolver_for_type(self, type, name, default_value):
|
||||
if not issubclass(type, ObjectType):
|
||||
return
|
||||
resolver = getattr(type, "resolve_{}".format(name), None)
|
||||
if not resolver:
|
||||
# If we don't find the resolver in the ObjectType class, then try to
|
||||
# find it in each of the interfaces
|
||||
interface_resolver = None
|
||||
for interface in type._meta.interfaces:
|
||||
if name not in interface._meta.fields:
|
||||
continue
|
||||
interface_resolver = getattr(interface, "resolve_{}".format(name), None)
|
||||
if interface_resolver:
|
||||
break
|
||||
resolver = interface_resolver
|
||||
# def get_resolver_for_type(self, type, name, default_value):
|
||||
# if not issubclass(type, ObjectType):
|
||||
# return
|
||||
# resolver = getattr(type, "resolve_{}".format(name), None)
|
||||
# if not resolver:
|
||||
# # If we don't find the resolver in the ObjectType class, then try to
|
||||
# # find it in each of the interfaces
|
||||
# interface_resolver = None
|
||||
# for interface in type._meta.interfaces:
|
||||
# if name not in interface._meta.fields:
|
||||
# continue
|
||||
# interface_resolver = getattr(interface, "resolve_{}".format(name), None)
|
||||
# if interface_resolver:
|
||||
# break
|
||||
# resolver = interface_resolver
|
||||
|
||||
# Only if is not decorated with classmethod
|
||||
if resolver:
|
||||
return get_unbound_function(resolver)
|
||||
# # Only if is not decorated with classmethod
|
||||
# if resolver:
|
||||
# return get_unbound_function(resolver)
|
||||
|
||||
default_resolver = type._meta.default_resolver or get_default_resolver()
|
||||
return partial(default_resolver, name, default_value)
|
||||
# default_resolver = type._meta.default_resolver or get_default_resolver()
|
||||
# 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)
|
||||
# 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)
|
||||
|
|
|
@ -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",
|
||||
"Intended Audience :: Developers",
|
||||
"Topic :: Software Development :: Libraries",
|
||||
"Programming Language :: Python :: 2",
|
||||
"Programming Language :: Python :: 2.7",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.3",
|
||||
"Programming Language :: Python :: 3.4",
|
||||
|
@ -86,8 +84,7 @@ setup(
|
|||
packages=find_packages(exclude=["tests", "tests.*", "examples"]),
|
||||
install_requires=[
|
||||
"six>=1.10.0,<2",
|
||||
"graphql-core>=2.1,<3",
|
||||
"graphql-relay>=0.4.5,<1",
|
||||
"graphql-core-next==1.0.3",
|
||||
"aniso8601>=3,<4",
|
||||
],
|
||||
tests_require=tests_require,
|
||||
|
|
4
tox.ini
4
tox.ini
|
@ -1,5 +1,5 @@
|
|||
[tox]
|
||||
envlist = flake8,py27,py34,py35,py36,py37,pre-commit,pypy,mypy
|
||||
envlist = flake8,py34,py35,py36,py37,pre-commit,pypy,mypy
|
||||
skipsdist = true
|
||||
|
||||
[testenv]
|
||||
|
@ -9,7 +9,7 @@ deps =
|
|||
setenv =
|
||||
PYTHONPATH = .:{envdir}
|
||||
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}
|
||||
|
||||
[testenv:pre-commit]
|
||||
|
|
Loading…
Reference in New Issue
Block a user