diff --git a/.travis.yml b/.travis.yml index c935ec0d..71535d3f 100644 --- a/.travis.yml +++ b/.travis.yml @@ -25,6 +25,7 @@ install: if [ "$TEST_TYPE" = build ]; then pip install --download-cache $HOME/.cache/pip/ pytest pytest-cov coveralls six pytest-django django-filter sqlalchemy_utils pip install --download-cache $HOME/.cache/pip psycopg2 > /dev/null 2>&1 + pip install --download-cache $HOME/.cache/pip/ -e . pip install --download-cache $HOME/.cache/pip/ -e .[django] pip install --download-cache $HOME/.cache/pip/ -e .[sqlalchemy] pip install django==$DJANGO_VERSION diff --git a/examples/cookbook_django/cookbook/ingredients/tests.py b/examples/cookbook_django/cookbook/ingredients/tests.py index 7ce503c2..49290204 100644 --- a/examples/cookbook_django/cookbook/ingredients/tests.py +++ b/examples/cookbook_django/cookbook/ingredients/tests.py @@ -1,3 +1,2 @@ -from django.test import TestCase # Create your tests here. diff --git a/examples/cookbook_django/cookbook/ingredients/views.py b/examples/cookbook_django/cookbook/ingredients/views.py index 91ea44a2..b8e4ee02 100644 --- a/examples/cookbook_django/cookbook/ingredients/views.py +++ b/examples/cookbook_django/cookbook/ingredients/views.py @@ -1,3 +1,2 @@ -from django.shortcuts import render # Create your views here. diff --git a/examples/cookbook_django/cookbook/recipes/migrations/0001_initial.py b/examples/cookbook_django/cookbook/recipes/migrations/0001_initial.py index 2071afc5..338c71a1 100644 --- a/examples/cookbook_django/cookbook/recipes/migrations/0001_initial.py +++ b/examples/cookbook_django/cookbook/recipes/migrations/0001_initial.py @@ -2,8 +2,8 @@ # Generated by Django 1.9 on 2015-12-04 18:20 from __future__ import unicode_literals -from django.db import migrations, models import django.db.models.deletion +from django.db import migrations, models class Migration(migrations.Migration): diff --git a/examples/cookbook_django/cookbook/recipes/tests.py b/examples/cookbook_django/cookbook/recipes/tests.py index 7ce503c2..49290204 100644 --- a/examples/cookbook_django/cookbook/recipes/tests.py +++ b/examples/cookbook_django/cookbook/recipes/tests.py @@ -1,3 +1,2 @@ -from django.test import TestCase # Create your tests here. diff --git a/examples/cookbook_django/cookbook/recipes/views.py b/examples/cookbook_django/cookbook/recipes/views.py index 91ea44a2..b8e4ee02 100644 --- a/examples/cookbook_django/cookbook/recipes/views.py +++ b/examples/cookbook_django/cookbook/recipes/views.py @@ -1,3 +1,2 @@ -from django.shortcuts import render # Create your views here. diff --git a/graphene/__init__.py b/graphene/__init__.py index 5eb2b5dd..a4eb6299 100644 --- a/graphene/__init__.py +++ b/graphene/__init__.py @@ -33,7 +33,8 @@ from graphene.core.fields import ( ) from graphene.utils import ( - resolve_only_args + resolve_only_args, + with_context ) __all__ = [ @@ -65,4 +66,5 @@ __all__ = [ 'ListField', 'NonNullField', 'FloatField', - 'resolve_only_args'] + 'resolve_only_args', + 'with_context'] diff --git a/graphene/contrib/django/debug/plugin.py b/graphene/contrib/django/debug/plugin.py index 70cd6741..2d930673 100644 --- a/graphene/contrib/django/debug/plugin.py +++ b/graphene/contrib/django/debug/plugin.py @@ -72,8 +72,8 @@ class DjangoDebugPlugin(Plugin): @contextmanager def context_execution(self, executor): - executor['root'] = WrappedRoot(root=executor['root']) + executor['root_value'] = WrappedRoot(root=executor.get('root_value')) executor['schema'] = self.wrap_schema(executor['schema']) - self.enable_instrumentation(executor['root']) + self.enable_instrumentation(executor['root_value']) yield executor self.disable_instrumentation() diff --git a/graphene/contrib/django/filter/filterset.py b/graphene/contrib/django/filter/filterset.py index 70f776be..6b9c8ac9 100644 --- a/graphene/contrib/django/filter/filterset.py +++ b/graphene/contrib/django/filter/filterset.py @@ -4,25 +4,25 @@ from django.db import models from django.utils.text import capfirst from django_filters import Filter, MultipleChoiceFilter from django_filters.filterset import FilterSet, FilterSetMetaclass -from graphql_relay.node.node import from_global_id from graphene.contrib.django.forms import (GlobalIDFormField, GlobalIDMultipleChoiceField) +from graphql_relay.node.node import from_global_id class GlobalIDFilter(Filter): field_class = GlobalIDFormField def filter(self, qs, value): - gid = from_global_id(value) - return super(GlobalIDFilter, self).filter(qs, gid.id) + _type, _id = from_global_id(value) + return super(GlobalIDFilter, self).filter(qs, _id) class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter): field_class = GlobalIDMultipleChoiceField def filter(self, qs, value): - gids = [from_global_id(v).id for v in value] + gids = [from_global_id(v)[1] for v in value] return super(GlobalIDMultipleChoiceFilter, self).filter(qs, gids) diff --git a/graphene/contrib/django/forms.py b/graphene/contrib/django/forms.py index d8062e39..8f8d0305 100644 --- a/graphene/contrib/django/forms.py +++ b/graphene/contrib/django/forms.py @@ -3,6 +3,7 @@ import binascii from django.core.exceptions import ValidationError from django.forms import CharField, Field, IntegerField, MultipleChoiceField from django.utils.translation import ugettext_lazy as _ + from graphql_relay import from_global_id @@ -16,13 +17,13 @@ class GlobalIDFormField(Field): return None try: - gid = from_global_id(value) + _type, _id = from_global_id(value) except (TypeError, ValueError, UnicodeDecodeError, binascii.Error): raise ValidationError(self.error_messages['invalid']) try: - IntegerField().clean(gid.id) - CharField().clean(gid.type) + IntegerField().clean(_id) + CharField().clean(_type) except ValidationError: raise ValidationError(self.error_messages['invalid']) diff --git a/graphene/contrib/django/tests/test_types.py b/graphene/contrib/django/tests/test_types.py index 42028a5e..bb996193 100644 --- a/graphene/contrib/django/tests/test_types.py +++ b/graphene/contrib/django/tests/test_types.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLObjectType +from graphql.type import GraphQLObjectType from mock import patch from graphene import Schema diff --git a/graphene/contrib/django/views.py b/graphene/contrib/django/views.py index 9a4bd96e..81f3ceba 100644 --- a/graphene/contrib/django/views.py +++ b/graphene/contrib/django/views.py @@ -11,6 +11,3 @@ class GraphQLView(BaseGraphQLView): executor=schema.executor, **kwargs ) - - def execute(self, *args, **kwargs): - return self.graphene_schema.execute(*args, **kwargs) diff --git a/graphene/contrib/sqlalchemy/tests/test_query.py b/graphene/contrib/sqlalchemy/tests/test_query.py index ce66d196..da8f8e11 100644 --- a/graphene/contrib/sqlalchemy/tests/test_query.py +++ b/graphene/contrib/sqlalchemy/tests/test_query.py @@ -7,7 +7,7 @@ from graphene import relay from graphene.contrib.sqlalchemy import (SQLAlchemyConnectionField, SQLAlchemyNode, SQLAlchemyObjectType) -from .models import Article, Base, Reporter, Editor +from .models import Article, Base, Editor, Reporter db = create_engine('sqlite:///test_sqlalchemy.sqlite3') diff --git a/graphene/contrib/sqlalchemy/tests/test_types.py b/graphene/contrib/sqlalchemy/tests/test_types.py index feffbc74..378411ae 100644 --- a/graphene/contrib/sqlalchemy/tests/test_types.py +++ b/graphene/contrib/sqlalchemy/tests/test_types.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLObjectType +from graphql.type import GraphQLObjectType from pytest import raises from graphene import Schema diff --git a/graphene/core/classtypes/enum.py b/graphene/core/classtypes/enum.py index d12201d4..97c8fe9f 100644 --- a/graphene/core/classtypes/enum.py +++ b/graphene/core/classtypes/enum.py @@ -1,9 +1,9 @@ import six -from graphql.core.type import GraphQLEnumType, GraphQLEnumValue +from graphql.type import GraphQLEnumType, GraphQLEnumValue -from .base import ClassTypeMeta, ClassType -from ..types.base import MountedType from ...utils.enum import Enum as PyEnum +from ..types.base import MountedType +from .base import ClassType, ClassTypeMeta class EnumMeta(ClassTypeMeta): diff --git a/graphene/core/classtypes/inputobjecttype.py b/graphene/core/classtypes/inputobjecttype.py index 43f4c897..9bff031e 100644 --- a/graphene/core/classtypes/inputobjecttype.py +++ b/graphene/core/classtypes/inputobjecttype.py @@ -1,6 +1,6 @@ from functools import partial -from graphql.core.type import GraphQLInputObjectType +from graphql.type import GraphQLInputObjectType from .base import FieldsClassType diff --git a/graphene/core/classtypes/interface.py b/graphene/core/classtypes/interface.py index c3aa3110..e7dd1870 100644 --- a/graphene/core/classtypes/interface.py +++ b/graphene/core/classtypes/interface.py @@ -1,7 +1,7 @@ from functools import partial import six -from graphql.core.type import GraphQLInterfaceType +from graphql.type import GraphQLInterfaceType from .base import FieldsClassTypeMeta from .objecttype import ObjectType, ObjectTypeMeta diff --git a/graphene/core/classtypes/objecttype.py b/graphene/core/classtypes/objecttype.py index e341ba97..ae7c94fb 100644 --- a/graphene/core/classtypes/objecttype.py +++ b/graphene/core/classtypes/objecttype.py @@ -1,7 +1,7 @@ from functools import partial import six -from graphql.core.type import GraphQLObjectType +from graphql.type import GraphQLObjectType from graphene import signals diff --git a/graphene/core/classtypes/scalar.py b/graphene/core/classtypes/scalar.py index 8d34eba0..79dbd3df 100644 --- a/graphene/core/classtypes/scalar.py +++ b/graphene/core/classtypes/scalar.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLScalarType +from graphql.type import GraphQLScalarType from ..types.base import MountedType from .base import ClassType diff --git a/graphene/core/classtypes/tests/test_enum.py b/graphene/core/classtypes/tests/test_enum.py index 1425d259..e7ea9f83 100644 --- a/graphene/core/classtypes/tests/test_enum.py +++ b/graphene/core/classtypes/tests/test_enum.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLEnumType +from graphql.type import GraphQLEnumType from graphene.core.schema import Schema diff --git a/graphene/core/classtypes/tests/test_inputobjecttype.py b/graphene/core/classtypes/tests/test_inputobjecttype.py index 2268d46f..98c6ba80 100644 --- a/graphene/core/classtypes/tests/test_inputobjecttype.py +++ b/graphene/core/classtypes/tests/test_inputobjecttype.py @@ -1,5 +1,5 @@ -from graphql.core.type import GraphQLInputObjectType +from graphql.type import GraphQLInputObjectType from graphene.core.schema import Schema from graphene.core.types import String diff --git a/graphene/core/classtypes/tests/test_interface.py b/graphene/core/classtypes/tests/test_interface.py index 7994659a..d47df1e0 100644 --- a/graphene/core/classtypes/tests/test_interface.py +++ b/graphene/core/classtypes/tests/test_interface.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType +from graphql.type import GraphQLInterfaceType, GraphQLObjectType from py.test import raises from graphene.core.schema import Schema diff --git a/graphene/core/classtypes/tests/test_mutation.py b/graphene/core/classtypes/tests/test_mutation.py index 85dd2368..2d3cfab4 100644 --- a/graphene/core/classtypes/tests/test_mutation.py +++ b/graphene/core/classtypes/tests/test_mutation.py @@ -1,5 +1,5 @@ -from graphql.core.type import GraphQLObjectType +from graphql.type import GraphQLObjectType from graphene.core.schema import Schema from graphene.core.types import String diff --git a/graphene/core/classtypes/tests/test_objecttype.py b/graphene/core/classtypes/tests/test_objecttype.py index 5e71ab73..c554dbbf 100644 --- a/graphene/core/classtypes/tests/test_objecttype.py +++ b/graphene/core/classtypes/tests/test_objecttype.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLObjectType +from graphql.type import GraphQLObjectType from py.test import raises from graphene.core.schema import Schema diff --git a/graphene/core/classtypes/tests/test_scalar.py b/graphene/core/classtypes/tests/test_scalar.py index a6e37881..8c2e17c8 100644 --- a/graphene/core/classtypes/tests/test_scalar.py +++ b/graphene/core/classtypes/tests/test_scalar.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLScalarType +from graphql.type import GraphQLScalarType from ...schema import Schema from ..scalar import Scalar @@ -6,7 +6,7 @@ from ..scalar import Scalar def test_custom_scalar(): import datetime - from graphql.core.language import ast + from graphql.language import ast class DateTimeScalar(Scalar): '''DateTimeScalar Documentation''' diff --git a/graphene/core/classtypes/tests/test_uniontype.py b/graphene/core/classtypes/tests/test_uniontype.py index 308b2ce0..0b456776 100644 --- a/graphene/core/classtypes/tests/test_uniontype.py +++ b/graphene/core/classtypes/tests/test_uniontype.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLUnionType +from graphql.type import GraphQLUnionType from graphene.core.schema import Schema from graphene.core.types import String @@ -25,4 +25,4 @@ def test_uniontype(): assert isinstance(object_type, GraphQLUnionType) assert Thing._meta.type_name == 'Thing' assert object_type.description == 'Thing union description' - assert object_type.get_possible_types() == [schema.T(Human), schema.T(Pet)] + assert object_type.get_types() == [schema.T(Human), schema.T(Pet)] diff --git a/graphene/core/classtypes/uniontype.py b/graphene/core/classtypes/uniontype.py index 24c3d441..2d545b59 100644 --- a/graphene/core/classtypes/uniontype.py +++ b/graphene/core/classtypes/uniontype.py @@ -1,7 +1,7 @@ from functools import partial import six -from graphql.core.type import GraphQLUnionType +from graphql.type import GraphQLUnionType from .base import FieldsClassType, FieldsClassTypeMeta, FieldsOptions diff --git a/graphene/core/schema.py b/graphene/core/schema.py index 81ded66c..966e1fd2 100644 --- a/graphene/core/schema.py +++ b/graphene/core/schema.py @@ -1,12 +1,9 @@ import inspect -from collections import OrderedDict -from graphql.core.execution.executor import Executor -from graphql.core.execution.middlewares.sync import \ - SynchronousExecutionMiddleware -from graphql.core.type import GraphQLSchema as _GraphQLSchema -from graphql.core.utils.introspection_query import introspection_query -from graphql.core.utils.schema_printer import print_schema +from graphql import graphql +from graphql.type import GraphQLSchema as _GraphQLSchema +from graphql.utils.introspection_query import introspection_query +from graphql.utils.schema_printer import print_schema from graphene import signals @@ -68,9 +65,6 @@ class Schema(object): @property def executor(self): - if not self._executor: - self._executor = Executor( - [SynchronousExecutionMiddleware()], map_type=OrderedDict) return self._executor @executor.setter @@ -121,10 +115,19 @@ class Schema(object): def types(self): return self._types_names - def execute(self, request='', root=None, args=None, **kwargs): - kwargs = dict(kwargs, request=request, root=root, args=args, schema=self.schema) + def execute(self, request_string='', root_value=None, variable_values=None, + context_value=None, operation_name=None, executor=None): + kwargs = dict( + schema=self.schema, + request_string=request_string, + root_value=root_value, + context_value=context_value, + variable_values=variable_values, + operation_name=operation_name, + executor=executor or self._executor + ) with self.plugins.context_execution(**kwargs) as execute_kwargs: - return self.executor.execute(**execute_kwargs) + return graphql(**execute_kwargs) def introspect(self): - return self.execute(introspection_query).data + return graphql(self.schema, introspection_query).data diff --git a/graphene/core/tests/test_mutations.py b/graphene/core/tests/test_mutations.py index c5a26daa..428340a6 100644 --- a/graphene/core/tests/test_mutations.py +++ b/graphene/core/tests/test_mutations.py @@ -58,6 +58,6 @@ def test_execute_mutations(): 'result': '5', } } - result = schema.execute(query, root=object()) + result = schema.execute(query, root_value=object()) assert not result.errors assert result.data == expected diff --git a/graphene/core/tests/test_old_fields.py b/graphene/core/tests/test_old_fields.py index 3f24aedf..a1d8ac60 100644 --- a/graphene/core/tests/test_old_fields.py +++ b/graphene/core/tests/test_old_fields.py @@ -1,6 +1,5 @@ -from graphql.core.type import (GraphQLBoolean, GraphQLField, GraphQLFloat, - GraphQLID, GraphQLInt, GraphQLNonNull, - GraphQLString) +from graphql.type import (GraphQLBoolean, GraphQLField, GraphQLFloat, + GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLString) from py.test import raises from graphene.core.fields import (BooleanField, Field, FloatField, IDField, @@ -94,7 +93,7 @@ def test_field_resolve(): f = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field() f.contribute_to_class(MyOt, 'field_name') field_type = schema.T(f) - assert 'RESOLVED' == field_type.resolver(MyOt, None, None) + assert 'RESOLVED' == field_type.resolver(MyOt, None, None, None) def test_field_resolve_type_custom(): diff --git a/graphene/core/tests/test_query.py b/graphene/core/tests/test_query.py index 5fbe2faa..57ab91c2 100644 --- a/graphene/core/tests/test_query.py +++ b/graphene/core/tests/test_query.py @@ -1,7 +1,7 @@ -from graphql.core import graphql -from graphql.core.type import GraphQLSchema +from graphql import graphql +from graphql.type import GraphQLSchema from graphene.core.fields import Field from graphene.core.schema import Schema @@ -40,7 +40,7 @@ Human_type = schema.T(Human) def test_type(): assert Human._meta.fields_map['name'].resolver( - Human(object()), {}, None) == 'Peter' + Human(object()), {}, None, None) == 'Peter' def test_query(): @@ -59,6 +59,6 @@ def test_query(): 'type': 'Dog' } } - result = graphql(schema, query, root=Human(object())) + result = graphql(schema, query, root_value=Human(object())) assert not result.errors assert result.data == expected diff --git a/graphene/core/tests/test_schema.py b/graphene/core/tests/test_schema.py index 189111a1..a7e4c2e1 100644 --- a/graphene/core/tests/test_schema.py +++ b/graphene/core/tests/test_schema.py @@ -1,4 +1,4 @@ -from graphql.core import graphql +from graphql import graphql from py.test import raises from graphene import Interface, List, ObjectType, Schema, String @@ -63,7 +63,7 @@ def test_query_schema_graphql(): 'type': 'Dog' } } - result = graphql(schema.schema, query, root=Human(object())) + result = graphql(schema.schema, query, root_value=Human(object())) assert not result.errors assert result.data == expected @@ -84,7 +84,7 @@ def test_query_schema_execute(): 'type': 'Dog' } } - result = schema.execute(query, root=object()) + result = schema.execute(query, root_value=object()) assert not result.errors assert result.data == expected @@ -93,8 +93,8 @@ def test_schema_get_type_map(): assert_equal_lists( schema.schema.get_type_map().keys(), ['__Field', 'String', 'Pet', 'Character', '__InputValue', - '__Directive', '__TypeKind', '__Schema', '__Type', 'Human', - '__EnumValue', 'Boolean']) + '__Directive', '__DirectiveLocation', '__TypeKind', '__Schema', + '__Type', 'Human', '__EnumValue', 'Boolean']) def test_schema_no_query(): @@ -156,6 +156,10 @@ def test_lazytype(): def test_schema_str(): expected = """ +schema { + query: Human +} + interface Character { name: String } diff --git a/graphene/core/types/argument.py b/graphene/core/types/argument.py index b10aff21..80039ede 100644 --- a/graphene/core/types/argument.py +++ b/graphene/core/types/argument.py @@ -1,7 +1,7 @@ from functools import wraps from itertools import chain -from graphql.core.type import GraphQLArgument +from graphql.type import GraphQLArgument from ...utils import ProxySnakeDict from .base import ArgumentType, GroupNamedType, NamedType, OrderedType @@ -57,7 +57,7 @@ def to_arguments(*args, **kwargs): def snake_case_args(resolver): @wraps(resolver) - def wrapped_resolver(instance, args, info): - return resolver(instance, ProxySnakeDict(args), info) + def wrapped_resolver(instance, args, context, info): + return resolver(instance, ProxySnakeDict(args), context, info) return wrapped_resolver diff --git a/graphene/core/types/custom_scalars.py b/graphene/core/types/custom_scalars.py index 2dad3c64..bd33df76 100644 --- a/graphene/core/types/custom_scalars.py +++ b/graphene/core/types/custom_scalars.py @@ -1,7 +1,7 @@ import json -import iso8601 -from graphql.core.language import ast +import iso8601 +from graphql.language import ast from ...core.classtypes.scalar import Scalar diff --git a/graphene/core/types/definitions.py b/graphene/core/types/definitions.py index 14cbc29d..396ed0dd 100644 --- a/graphene/core/types/definitions.py +++ b/graphene/core/types/definitions.py @@ -1,5 +1,5 @@ import six -from graphql.core.type import GraphQLList, GraphQLNonNull +from graphql.type import GraphQLList, GraphQLNonNull from .base import LazyType, MountedType, MountType diff --git a/graphene/core/types/field.py b/graphene/core/types/field.py index f825f861..351182d1 100644 --- a/graphene/core/types/field.py +++ b/graphene/core/types/field.py @@ -2,9 +2,10 @@ from collections import OrderedDict from functools import wraps import six -from graphql.core.type import GraphQLField, GraphQLInputObjectField +from graphql.type import GraphQLField, GraphQLInputObjectField from ...utils import maybe_func +from ...utils.wrap_resolver_function import wrap_resolver_function from ..classtypes.base import FieldsClassType from ..classtypes.inputobjecttype import InputObjectType from ..classtypes.mutation import Mutation @@ -105,14 +106,15 @@ class Field(NamedType, OrderedType): assert len(arguments) == 0 arguments = type_objecttype.get_arguments() resolver = getattr(type_objecttype, 'mutate') + resolver = wrap_resolver_function(resolver) else: - my_resolver = resolver + my_resolver = wrap_resolver_function(resolver) @wraps(my_resolver) - def wrapped_func(instance, args, info): + def wrapped_func(instance, args, context, info): if not isinstance(instance, self.object_type): instance = self.object_type(_root=instance) - return my_resolver(instance, args, info) + return my_resolver(instance, args, context, info) resolver = wrapped_func assert type, 'Internal type for field %s is None' % str(self) diff --git a/graphene/core/types/scalars.py b/graphene/core/types/scalars.py index 9d7f5aeb..4f178cb9 100644 --- a/graphene/core/types/scalars.py +++ b/graphene/core/types/scalars.py @@ -1,5 +1,5 @@ -from graphql.core.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, - GraphQLInt, GraphQLString) +from graphql.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, GraphQLInt, + GraphQLString) from .base import MountedType diff --git a/graphene/core/types/tests/test_argument.py b/graphene/core/types/tests/test_argument.py index 0263496c..4482c11c 100644 --- a/graphene/core/types/tests/test_argument.py +++ b/graphene/core/types/tests/test_argument.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLArgument +from graphql.type import GraphQLArgument from pytest import raises from graphene.core.schema import Schema @@ -48,7 +48,7 @@ def test_to_arguments_wrong_type(): def test_snake_case_args(): - def resolver(instance, args, info): + def resolver(instance, args, context, info): return args['my_arg']['inner_arg'] r = snake_case_args(resolver) - assert r(None, {'myArg': {'innerArg': 3}}, None) == 3 + assert r(None, {'myArg': {'innerArg': 3}}, None, None) == 3 diff --git a/graphene/core/types/tests/test_custom_scalars.py b/graphene/core/types/tests/test_custom_scalars.py index 49c9a9c7..28012b36 100644 --- a/graphene/core/types/tests/test_custom_scalars.py +++ b/graphene/core/types/tests/test_custom_scalars.py @@ -1,6 +1,5 @@ import iso8601 - -from graphql.core.language.ast import StringValue +from graphql.language.ast import StringValue from ..custom_scalars import DateTime diff --git a/graphene/core/types/tests/test_definitions.py b/graphene/core/types/tests/test_definitions.py index d56843d8..a87e89ee 100644 --- a/graphene/core/types/tests/test_definitions.py +++ b/graphene/core/types/tests/test_definitions.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLList, GraphQLNonNull, GraphQLString +from graphql.type import GraphQLList, GraphQLNonNull, GraphQLString from graphene.core.schema import Schema diff --git a/graphene/core/types/tests/test_field.py b/graphene/core/types/tests/test_field.py index 049ee92c..2d4301ef 100644 --- a/graphene/core/types/tests/test_field.py +++ b/graphene/core/types/tests/test_field.py @@ -1,5 +1,4 @@ -from graphql.core.type import (GraphQLField, GraphQLInputObjectField, - GraphQLString) +from graphql.type import GraphQLField, GraphQLInputObjectField, GraphQLString from graphene.core.schema import Schema from graphene.core.types import InputObjectType, ObjectType @@ -25,7 +24,7 @@ def test_field_internal_type(): assert field.attname == 'my_field' assert isinstance(type, GraphQLField) assert type.description == 'My argument' - assert type.resolver(None, {}, None) == 'RESOLVED' + assert type.resolver(None, {}, None, None) == 'RESOLVED' assert type.type == GraphQLString @@ -44,7 +43,7 @@ def test_field_objectype_resolver(): type = schema.T(field) assert isinstance(type, GraphQLField) assert type.description == 'Custom description' - assert type.resolver(Query(), {}, None) == 'RESOLVED' + assert type.resolver(Query(), {}, None, None) == 'RESOLVED' def test_field_custom_name(): @@ -143,7 +142,7 @@ def test_field_resolve_argument(): schema = Schema(query=Query) type = schema.T(field) - assert type.resolver(None, {'firstName': 'Peter'}, None) == 'Peter' + assert type.resolver(None, {'firstName': 'Peter'}, None, None) == 'Peter' def test_field_resolve_vars(): @@ -160,7 +159,7 @@ def test_field_resolve_vars(): { hello(firstName:$firstName) } - """, args={"firstName": "Serkan"}) + """, variable_values={"firstName": "Serkan"}) expected = { 'hello': 'Hello Serkan' diff --git a/graphene/core/types/tests/test_scalars.py b/graphene/core/types/tests/test_scalars.py index 39fd6063..124bb8c4 100644 --- a/graphene/core/types/tests/test_scalars.py +++ b/graphene/core/types/tests/test_scalars.py @@ -1,5 +1,5 @@ -from graphql.core.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, - GraphQLInt, GraphQLString) +from graphql.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, GraphQLInt, + GraphQLString) from graphene.core.schema import Schema diff --git a/graphene/relay/fields.py b/graphene/relay/fields.py index aac1f7df..da9d4af7 100644 --- a/graphene/relay/fields.py +++ b/graphene/relay/fields.py @@ -1,9 +1,11 @@ import six + from graphql_relay.node.node import from_global_id from ..core.fields import Field from ..core.types.definitions import NonNull from ..core.types.scalars import ID, Int, String +from ..utils import with_context class ConnectionField(Field): @@ -65,14 +67,13 @@ class NodeField(Field): object_type or Node, id=id, *args, **kwargs) self.field_object_type = object_type - def id_fetcher(self, global_id, info): + def id_fetcher(self, global_id, context, info): from graphene.relay.utils import is_node schema = info.schema.graphene_schema try: - resolved_global_id = from_global_id(global_id) + _type, _id = from_global_id(global_id) except: return None - _type, _id = resolved_global_id.type, resolved_global_id.id object_type = schema.get_type(_type) if isinstance(self.field_object_type, six.string_types): field_object_type = schema.get_type(self.field_object_type) @@ -81,11 +82,12 @@ class NodeField(Field): if not is_node(object_type) or (self.field_object_type and object_type != field_object_type): return - return object_type.get_node(_id, info) + return object_type.get_node(_id, context, info) - def resolver(self, instance, args, info): + @with_context + def resolver(self, instance, args, context, info): global_id = args.get('id') - return self.id_fetcher(global_id, info) + return self.id_fetcher(global_id, context, info) class GlobalIDField(Field): diff --git a/graphene/relay/tests/test_mutations.py b/graphene/relay/tests/test_mutations.py index 82329519..d569bd7e 100644 --- a/graphene/relay/tests/test_mutations.py +++ b/graphene/relay/tests/test_mutations.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLInputObjectField +from graphql.type import GraphQLInputObjectField import graphene from graphene import relay @@ -76,6 +76,6 @@ def test_execute_mutations(): 'result': '5', } } - result = schema.execute(query, root=object()) + result = schema.execute(query, root_value=object()) assert not result.errors assert result.data == expected diff --git a/graphene/relay/tests/test_query.py b/graphene/relay/tests/test_query.py index b49ac791..4e94d9fd 100644 --- a/graphene/relay/tests/test_query.py +++ b/graphene/relay/tests/test_query.py @@ -1,8 +1,8 @@ import pytest -from graphql.core.type import GraphQLID, GraphQLNonNull +from graphql.type import GraphQLID, GraphQLNonNull import graphene -from graphene import relay +from graphene import relay, with_context schema = graphene.Schema() @@ -24,8 +24,9 @@ class SpecialNode(relay.Node): value = graphene.String() @classmethod - def get_node(cls, id, info): - value = "!!!" if info.request_context.get('is_special') else "???" + @with_context + def get_node(cls, id, context, info): + value = "!!!" if context.get('is_special') else "???" return SpecialNode(id=id, value=value) @@ -108,7 +109,7 @@ def test_get_node_info(specialness, value): 'value': value, }, } - result = schema.execute(query, request_context={'is_special': specialness}) + result = schema.execute(query, context_value={'is_special': specialness}) assert not result.errors assert result.data == expected diff --git a/graphene/relay/tests/test_types.py b/graphene/relay/tests/test_types.py index d9f64c00..ff510cab 100644 --- a/graphene/relay/tests/test_types.py +++ b/graphene/relay/tests/test_types.py @@ -1,4 +1,4 @@ -from graphql.core.type import GraphQLList +from graphql.type import GraphQLList from pytest import raises import graphene diff --git a/graphene/relay/types.py b/graphene/relay/types.py index d539bce7..6df9d7f6 100644 --- a/graphene/relay/types.py +++ b/graphene/relay/types.py @@ -4,6 +4,7 @@ from collections import Iterable from functools import wraps import six + from graphql_relay.connection.arrayconnection import connection_from_list from graphql_relay.node.node import to_global_id @@ -14,6 +15,7 @@ from ..core.types import Boolean, Field, List, String from ..core.types.argument import ArgumentsGroup from ..core.types.definitions import NonNull from ..utils import memoize +from ..utils.wrap_resolver_function import has_context from .fields import GlobalIDField @@ -107,7 +109,7 @@ class NodeMeta(InterfaceMeta): get_node = getattr(cls, 'get_node', None) assert get_node, 'get_node classmethod not found in %s Node' % cls assert callable(get_node), 'get_node have to be callable' - args = 3 + args = 4 if isinstance(get_node, staticmethod): args -= 1 @@ -119,12 +121,15 @@ class NodeMeta(InterfaceMeta): @staticmethod @wraps(get_node) - def wrapped_node(*node_args): - if len(node_args) < args: - node_args += (None, ) - return get_node(*node_args[:-1]) - - setattr(cls, 'get_node', wrapped_node) + def wrapped_node(id, context=None, info=None): + node_args = [id, info, context] + if has_context(get_node): + return get_node(*node_args[:get_node_num_args - 1], context=context) + if get_node_num_args - 1 == 0: + return get_node(id) + return get_node(*node_args[:get_node_num_args - 1]) + node_func = wrapped_node + setattr(cls, 'get_node', node_func) def construct(cls, *args, **kwargs): cls = super(NodeMeta, cls).construct(*args, **kwargs) diff --git a/graphene/utils/__init__.py b/graphene/utils/__init__.py index 34e4ad9a..2ed0f036 100644 --- a/graphene/utils/__init__.py +++ b/graphene/utils/__init__.py @@ -5,8 +5,10 @@ from .maybe_func import maybe_func from .misc import enum_to_graphql_enum from .resolve_only_args import resolve_only_args from .lazylist import LazyList +from .wrap_resolver_function import with_context, wrap_resolver_function __all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict', 'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum', - 'resolve_only_args', 'LazyList'] + 'resolve_only_args', 'LazyList', 'with_context', + 'wrap_resolver_function'] diff --git a/graphene/utils/misc.py b/graphene/utils/misc.py index e7d1cc07..9fc9d493 100644 --- a/graphene/utils/misc.py +++ b/graphene/utils/misc.py @@ -1,6 +1,6 @@ from collections import OrderedDict -from graphql.core.type import GraphQLEnumType, GraphQLEnumValue +from graphql.type import GraphQLEnumType, GraphQLEnumValue def enum_to_graphql_enum(enumeration): diff --git a/graphene/utils/tests/test_misc.py b/graphene/utils/tests/test_misc.py index 468c621c..7f5f596d 100644 --- a/graphene/utils/tests/test_misc.py +++ b/graphene/utils/tests/test_misc.py @@ -1,6 +1,6 @@ import collections -from graphql.core.type import GraphQLEnumType +from graphql.type import GraphQLEnumType from ..misc import enum_to_graphql_enum diff --git a/graphene/utils/tests/test_str_converter.py b/graphene/utils/tests/test_str_converter.py index 83e3c2fa..1e4880c2 100644 --- a/graphene/utils/tests/test_str_converter.py +++ b/graphene/utils/tests/test_str_converter.py @@ -1,5 +1,5 @@ # coding: utf-8 -from ..str_converters import to_camel_case, to_snake_case, to_const +from ..str_converters import to_camel_case, to_const, to_snake_case def test_snake_case(): diff --git a/graphene/utils/wrap_resolver_function.py b/graphene/utils/wrap_resolver_function.py new file mode 100644 index 00000000..c8bc9ec9 --- /dev/null +++ b/graphene/utils/wrap_resolver_function.py @@ -0,0 +1,20 @@ +from functools import wraps + + +def with_context(func): + setattr(func, 'with_context', 'context') + return func + + +def has_context(func): + return getattr(func, 'with_context', None) + + +def wrap_resolver_function(func): + @wraps(func) + def inner(self, args, context, info): + if has_context(func): + return func(self, args, context, info) + # For old compatibility + return func(self, args, info) + return inner diff --git a/setup.py b/setup.py index d0476511..5105656a 100644 --- a/setup.py +++ b/setup.py @@ -24,7 +24,7 @@ class PyTest(TestCommand): setup( name='graphene', - version='0.8.1', + version='0.8.2', description='GraphQL Framework for Python', long_description=open('README.rst').read(), @@ -55,8 +55,8 @@ setup( install_requires=[ 'six>=1.10.0', - 'graphql-core>=0.4.9', - 'graphql-relay==0.3.3', + 'graphql-core==0.5b3', + 'graphql-relay==0.4b1', 'iso8601', ], tests_require=[ @@ -73,7 +73,7 @@ setup( 'django': [ 'Django>=1.6.0', 'singledispatch>=3.4.0.3', - 'graphql-django-view>=1.1.0', + 'graphql-django-view==1.3b1', ], 'sqlalchemy': [ 'sqlalchemy', diff --git a/tox.ini b/tox.ini index a3a5b251..9ff2f673 100644 --- a/tox.ini +++ b/tox.ini @@ -7,9 +7,9 @@ deps= pytest>=2.7.2 django>=1.8.0,<1.9 pytest-django - graphql-django-view>=1.0.0 - graphql-core==0.4.9 - graphql-relay==0.3.3 + graphql-django-view==1.3b1 + graphql-core==0.5b3 + graphql-relay==0.4b1 six blinker singledispatch