From 8a7a32113609c39248c439bdd0a5ecc872560994 Mon Sep 17 00:00:00 2001 From: Paul Hallett Date: Sat, 4 May 2019 20:39:28 +0100 Subject: [PATCH] Start porting to graphql-core-next --- Makefile | 7 + graphene/__init__.py | 4 +- graphene/pyutils/compat.py | 2 - graphene/relay/connection.py | 145 +++++- graphene/relay/connectiontypes.py | 42 ++ graphene/relay/node.py | 4 +- graphene/relay/tests/test_connection_query.py | 2 +- graphene/relay/tests/test_global_id.py | 2 +- graphene/relay/tests/test_node.py | 2 +- graphene/relay/utils.py | 19 + graphene/types/__init__.py | 4 +- graphene/types/enum.py | 10 +- graphene/types/generic.py | 20 +- graphene/types/scalars.py | 13 +- graphene/types/schema.py | 108 +--- graphene/types/tests/test_datetime.py | 2 +- graphene/types/tests/test_enum.py | 117 ++--- graphene/types/tests/test_query.py | 4 +- graphene/types/tests/test_typemap.py | 462 ++++++++--------- graphene/types/tests/test_uuid.py | 1 - graphene/types/typemap.py | 478 +++++++++--------- graphene/utils/__init__.py | 7 + graphene/utils/helpers.py | 13 + setup.py | 5 +- tox.ini | 4 +- 25 files changed, 788 insertions(+), 689 deletions(-) create mode 100644 graphene/relay/connectiontypes.py create mode 100644 graphene/relay/utils.py create mode 100644 graphene/utils/helpers.py diff --git a/Makefile b/Makefile index c1a00054..8bb67e9e 100644 --- a/Makefile +++ b/Makefile @@ -9,3 +9,10 @@ docs: pip install -r requirements.txt &&\ make html &&\ cd - + + +dev-setup: + pip install -e ".[test]" + +tests: + py.test graphene \ No newline at end of file diff --git a/graphene/__init__.py b/graphene/__init__.py index c922aea2..2e0d21c4 100644 --- a/graphene/__init__.py +++ b/graphene/__init__.py @@ -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", ] diff --git a/graphene/pyutils/compat.py b/graphene/pyutils/compat.py index 3d3ce2fe..ecacd860 100644 --- a/graphene/pyutils/compat.py +++ b/graphene/pyutils/compat.py @@ -2,8 +2,6 @@ from __future__ import absolute_import import six -from graphql.pyutils.compat import Enum - try: from inspect import signature except ImportError: diff --git a/graphene/relay/connection.py b/graphene/relay/connection.py index 047f2b4d..72499160 100644 --- a/graphene/relay/connection.py +++ b/graphene/relay/connection.py @@ -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: diff --git a/graphene/relay/connectiontypes.py b/graphene/relay/connectiontypes.py new file mode 100644 index 00000000..b5d674fd --- /dev/null +++ b/graphene/relay/connectiontypes.py @@ -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, + } diff --git a/graphene/relay/node.py b/graphene/relay/node.py index d9c4c0f6..7e1ad94b 100644 --- a/graphene/relay/node.py +++ b/graphene/relay/node.py @@ -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): """ diff --git a/graphene/relay/tests/test_connection_query.py b/graphene/relay/tests/test_connection_query.py index be6ee8c7..105d9ff7 100644 --- a/graphene/relay/tests/test_connection_query.py +++ b/graphene/relay/tests/test_connection_query.py @@ -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 diff --git a/graphene/relay/tests/test_global_id.py b/graphene/relay/tests/test_global_id.py index 6d328f23..62fb817b 100644 --- a/graphene/relay/tests/test_global_id.py +++ b/graphene/relay/tests/test_global_id.py @@ -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 diff --git a/graphene/relay/tests/test_node.py b/graphene/relay/tests/test_node.py index fbce1d54..6cc6078b 100644 --- a/graphene/relay/tests/test_node.py +++ b/graphene/relay/tests/test_node.py @@ -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 diff --git a/graphene/relay/utils.py b/graphene/relay/utils.py new file mode 100644 index 00000000..400ebfe5 --- /dev/null +++ b/graphene/relay/utils.py @@ -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 \ No newline at end of file diff --git a/graphene/types/__init__.py b/graphene/types/__init__.py index 96591605..66c24751 100644 --- a/graphene/types/__init__.py +++ b/graphene/types/__init__.py @@ -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", ] diff --git a/graphene/types/enum.py b/graphene/types/enum.py index 6e6bab8f..62863ea3 100644 --- a/graphene/types/enum.py +++ b/graphene/types/enum.py @@ -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) diff --git a/graphene/types/generic.py b/graphene/types/generic.py index e5470dd9..81f03058 100644 --- a/graphene/types/generic.py +++ b/graphene/types/generic.py @@ -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 { diff --git a/graphene/types/scalars.py b/graphene/types/scalars.py index c5f43787..bb99a47f 100644 --- a/graphene/types/scalars.py +++ b/graphene/types/scalars.py @@ -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 diff --git a/graphene/types/schema.py b/graphene/types/schema.py index a885c88a..d52ded58 100644 --- a/graphene/types/schema.py +++ b/graphene/types/schema.py @@ -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 - ) diff --git a/graphene/types/tests/test_datetime.py b/graphene/types/tests/test_datetime.py index 0d9ee114..1a8ea0fa 100644 --- a/graphene/types/tests/test_datetime.py +++ b/graphene/types/tests/test_datetime.py @@ -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 diff --git a/graphene/types/tests/test_enum.py b/graphene/types/tests/test_enum.py index 6086f54c..010e9848 100644 --- a/graphene/types/tests/test_enum.py +++ b/graphene/types/tests/test_enum.py @@ -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(): diff --git a/graphene/types/tests/test_query.py b/graphene/types/tests/test_query.py index 8681e462..f6f0fdd6 100644 --- a/graphene/types/tests/test_query.py +++ b/graphene/types/tests/test_query.py @@ -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) diff --git a/graphene/types/tests/test_typemap.py b/graphene/types/tests/test_typemap.py index f713726f..238cb966 100644 --- a/graphene/types/tests/test_typemap.py +++ b/graphene/types/tests/test_typemap.py @@ -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) diff --git a/graphene/types/tests/test_uuid.py b/graphene/types/tests/test_uuid.py index 2280b41f..455d721a 100644 --- a/graphene/types/tests/test_uuid.py +++ b/graphene/types/tests/test_uuid.py @@ -9,7 +9,6 @@ class Query(ObjectType): def resolve_uuid(self, info, input): return input - schema = Schema(query=Query) diff --git a/graphene/types/typemap.py b/graphene/types/typemap.py index 9edb8518..67a4c5a5 100644 --- a/graphene/types/typemap.py +++ b/graphene/types/typemap.py @@ -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) diff --git a/graphene/utils/__init__.py b/graphene/utils/__init__.py index e69de29b..f5acd0c2 100644 --- a/graphene/utils/__init__.py +++ b/graphene/utils/__init__.py @@ -0,0 +1,7 @@ +from .helpers import base64, unbase64, is_str + +__all__ = [ + "base64", + "unbase64", + "is_str" +] \ No newline at end of file diff --git a/graphene/utils/helpers.py b/graphene/utils/helpers.py new file mode 100644 index 00000000..effe5985 --- /dev/null +++ b/graphene/utils/helpers.py @@ -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) \ No newline at end of file diff --git a/setup.py b/setup.py index 48e5be35..8e49c6be 100644 --- a/setup.py +++ b/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, diff --git a/tox.ini b/tox.ini index 2b7ae59c..a6c71999 100644 --- a/tox.ini +++ b/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]