Merge pull request #159 from graphql-python/core-update

Core update GraphQL-core 0.5.0
This commit is contained in:
Syrus Akbary 2016-05-12 00:08:37 -07:00
commit 3dcb53ac07
54 changed files with 158 additions and 125 deletions

View File

@ -25,6 +25,7 @@ install:
if [ "$TEST_TYPE" = build ]; then 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/ 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 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 .[django]
pip install --download-cache $HOME/.cache/pip/ -e .[sqlalchemy] pip install --download-cache $HOME/.cache/pip/ -e .[sqlalchemy]
pip install django==$DJANGO_VERSION pip install django==$DJANGO_VERSION

View File

@ -1,3 +1,2 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@ -1,3 +1,2 @@
from django.shortcuts import render
# Create your views here. # Create your views here.

View File

@ -2,8 +2,8 @@
# Generated by Django 1.9 on 2015-12-04 18:20 # Generated by Django 1.9 on 2015-12-04 18:20
from __future__ import unicode_literals from __future__ import unicode_literals
from django.db import migrations, models
import django.db.models.deletion import django.db.models.deletion
from django.db import migrations, models
class Migration(migrations.Migration): class Migration(migrations.Migration):

View File

@ -1,3 +1,2 @@
from django.test import TestCase
# Create your tests here. # Create your tests here.

View File

@ -1,3 +1,2 @@
from django.shortcuts import render
# Create your views here. # Create your views here.

View File

@ -33,7 +33,8 @@ from graphene.core.fields import (
) )
from graphene.utils import ( from graphene.utils import (
resolve_only_args resolve_only_args,
with_context
) )
__all__ = [ __all__ = [
@ -65,4 +66,5 @@ __all__ = [
'ListField', 'ListField',
'NonNullField', 'NonNullField',
'FloatField', 'FloatField',
'resolve_only_args'] 'resolve_only_args',
'with_context']

View File

@ -72,8 +72,8 @@ class DjangoDebugPlugin(Plugin):
@contextmanager @contextmanager
def context_execution(self, executor): 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']) executor['schema'] = self.wrap_schema(executor['schema'])
self.enable_instrumentation(executor['root']) self.enable_instrumentation(executor['root_value'])
yield executor yield executor
self.disable_instrumentation() self.disable_instrumentation()

View File

@ -4,25 +4,25 @@ from django.db import models
from django.utils.text import capfirst from django.utils.text import capfirst
from django_filters import Filter, MultipleChoiceFilter from django_filters import Filter, MultipleChoiceFilter
from django_filters.filterset import FilterSet, FilterSetMetaclass from django_filters.filterset import FilterSet, FilterSetMetaclass
from graphql_relay.node.node import from_global_id
from graphene.contrib.django.forms import (GlobalIDFormField, from graphene.contrib.django.forms import (GlobalIDFormField,
GlobalIDMultipleChoiceField) GlobalIDMultipleChoiceField)
from graphql_relay.node.node import from_global_id
class GlobalIDFilter(Filter): class GlobalIDFilter(Filter):
field_class = GlobalIDFormField field_class = GlobalIDFormField
def filter(self, qs, value): def filter(self, qs, value):
gid = from_global_id(value) _type, _id = from_global_id(value)
return super(GlobalIDFilter, self).filter(qs, gid.id) return super(GlobalIDFilter, self).filter(qs, _id)
class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter): class GlobalIDMultipleChoiceFilter(MultipleChoiceFilter):
field_class = GlobalIDMultipleChoiceField field_class = GlobalIDMultipleChoiceField
def filter(self, qs, value): 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) return super(GlobalIDMultipleChoiceFilter, self).filter(qs, gids)

View File

@ -3,6 +3,7 @@ import binascii
from django.core.exceptions import ValidationError from django.core.exceptions import ValidationError
from django.forms import CharField, Field, IntegerField, MultipleChoiceField from django.forms import CharField, Field, IntegerField, MultipleChoiceField
from django.utils.translation import ugettext_lazy as _ from django.utils.translation import ugettext_lazy as _
from graphql_relay import from_global_id from graphql_relay import from_global_id
@ -16,13 +17,13 @@ class GlobalIDFormField(Field):
return None return None
try: try:
gid = from_global_id(value) _type, _id = from_global_id(value)
except (TypeError, ValueError, UnicodeDecodeError, binascii.Error): except (TypeError, ValueError, UnicodeDecodeError, binascii.Error):
raise ValidationError(self.error_messages['invalid']) raise ValidationError(self.error_messages['invalid'])
try: try:
IntegerField().clean(gid.id) IntegerField().clean(_id)
CharField().clean(gid.type) CharField().clean(_type)
except ValidationError: except ValidationError:
raise ValidationError(self.error_messages['invalid']) raise ValidationError(self.error_messages['invalid'])

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLObjectType from graphql.type import GraphQLObjectType
from mock import patch from mock import patch
from graphene import Schema from graphene import Schema

View File

@ -11,6 +11,3 @@ class GraphQLView(BaseGraphQLView):
executor=schema.executor, executor=schema.executor,
**kwargs **kwargs
) )
def execute(self, *args, **kwargs):
return self.graphene_schema.execute(*args, **kwargs)

View File

@ -7,7 +7,7 @@ from graphene import relay
from graphene.contrib.sqlalchemy import (SQLAlchemyConnectionField, from graphene.contrib.sqlalchemy import (SQLAlchemyConnectionField,
SQLAlchemyNode, SQLAlchemyObjectType) SQLAlchemyNode, SQLAlchemyObjectType)
from .models import Article, Base, Reporter, Editor from .models import Article, Base, Editor, Reporter
db = create_engine('sqlite:///test_sqlalchemy.sqlite3') db = create_engine('sqlite:///test_sqlalchemy.sqlite3')

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLObjectType from graphql.type import GraphQLObjectType
from pytest import raises from pytest import raises
from graphene import Schema from graphene import Schema

View File

@ -1,9 +1,9 @@
import six 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 ...utils.enum import Enum as PyEnum
from ..types.base import MountedType
from .base import ClassType, ClassTypeMeta
class EnumMeta(ClassTypeMeta): class EnumMeta(ClassTypeMeta):

View File

@ -1,6 +1,6 @@
from functools import partial from functools import partial
from graphql.core.type import GraphQLInputObjectType from graphql.type import GraphQLInputObjectType
from .base import FieldsClassType from .base import FieldsClassType

View File

@ -1,7 +1,7 @@
from functools import partial from functools import partial
import six import six
from graphql.core.type import GraphQLInterfaceType from graphql.type import GraphQLInterfaceType
from .base import FieldsClassTypeMeta from .base import FieldsClassTypeMeta
from .objecttype import ObjectType, ObjectTypeMeta from .objecttype import ObjectType, ObjectTypeMeta

View File

@ -1,7 +1,7 @@
from functools import partial from functools import partial
import six import six
from graphql.core.type import GraphQLObjectType from graphql.type import GraphQLObjectType
from graphene import signals from graphene import signals

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLScalarType from graphql.type import GraphQLScalarType
from ..types.base import MountedType from ..types.base import MountedType
from .base import ClassType from .base import ClassType

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLEnumType from graphql.type import GraphQLEnumType
from graphene.core.schema import Schema from graphene.core.schema import Schema

View File

@ -1,5 +1,5 @@
from graphql.core.type import GraphQLInputObjectType from graphql.type import GraphQLInputObjectType
from graphene.core.schema import Schema from graphene.core.schema import Schema
from graphene.core.types import String from graphene.core.types import String

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType from graphql.type import GraphQLInterfaceType, GraphQLObjectType
from py.test import raises from py.test import raises
from graphene.core.schema import Schema from graphene.core.schema import Schema

View File

@ -1,5 +1,5 @@
from graphql.core.type import GraphQLObjectType from graphql.type import GraphQLObjectType
from graphene.core.schema import Schema from graphene.core.schema import Schema
from graphene.core.types import String from graphene.core.types import String

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLObjectType from graphql.type import GraphQLObjectType
from py.test import raises from py.test import raises
from graphene.core.schema import Schema from graphene.core.schema import Schema

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLScalarType from graphql.type import GraphQLScalarType
from ...schema import Schema from ...schema import Schema
from ..scalar import Scalar from ..scalar import Scalar
@ -6,7 +6,7 @@ from ..scalar import Scalar
def test_custom_scalar(): def test_custom_scalar():
import datetime import datetime
from graphql.core.language import ast from graphql.language import ast
class DateTimeScalar(Scalar): class DateTimeScalar(Scalar):
'''DateTimeScalar Documentation''' '''DateTimeScalar Documentation'''

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLUnionType from graphql.type import GraphQLUnionType
from graphene.core.schema import Schema from graphene.core.schema import Schema
from graphene.core.types import String from graphene.core.types import String
@ -25,4 +25,4 @@ def test_uniontype():
assert isinstance(object_type, GraphQLUnionType) assert isinstance(object_type, GraphQLUnionType)
assert Thing._meta.type_name == 'Thing' assert Thing._meta.type_name == 'Thing'
assert object_type.description == 'Thing union description' 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)]

View File

@ -1,7 +1,7 @@
from functools import partial from functools import partial
import six import six
from graphql.core.type import GraphQLUnionType from graphql.type import GraphQLUnionType
from .base import FieldsClassType, FieldsClassTypeMeta, FieldsOptions from .base import FieldsClassType, FieldsClassTypeMeta, FieldsOptions

View File

@ -1,12 +1,9 @@
import inspect import inspect
from collections import OrderedDict
from graphql.core.execution.executor import Executor from graphql import graphql
from graphql.core.execution.middlewares.sync import \ from graphql.type import GraphQLSchema as _GraphQLSchema
SynchronousExecutionMiddleware from graphql.utils.introspection_query import introspection_query
from graphql.core.type import GraphQLSchema as _GraphQLSchema from graphql.utils.schema_printer import print_schema
from graphql.core.utils.introspection_query import introspection_query
from graphql.core.utils.schema_printer import print_schema
from graphene import signals from graphene import signals
@ -68,9 +65,6 @@ class Schema(object):
@property @property
def executor(self): def executor(self):
if not self._executor:
self._executor = Executor(
[SynchronousExecutionMiddleware()], map_type=OrderedDict)
return self._executor return self._executor
@executor.setter @executor.setter
@ -121,10 +115,19 @@ class Schema(object):
def types(self): def types(self):
return self._types_names return self._types_names
def execute(self, request='', root=None, args=None, **kwargs): def execute(self, request_string='', root_value=None, variable_values=None,
kwargs = dict(kwargs, request=request, root=root, args=args, schema=self.schema) 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: with self.plugins.context_execution(**kwargs) as execute_kwargs:
return self.executor.execute(**execute_kwargs) return graphql(**execute_kwargs)
def introspect(self): def introspect(self):
return self.execute(introspection_query).data return graphql(self.schema, introspection_query).data

View File

@ -58,6 +58,6 @@ def test_execute_mutations():
'result': '5', 'result': '5',
} }
} }
result = schema.execute(query, root=object()) result = schema.execute(query, root_value=object())
assert not result.errors assert not result.errors
assert result.data == expected assert result.data == expected

View File

@ -1,6 +1,5 @@
from graphql.core.type import (GraphQLBoolean, GraphQLField, GraphQLFloat, from graphql.type import (GraphQLBoolean, GraphQLField, GraphQLFloat,
GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLID, GraphQLInt, GraphQLNonNull, GraphQLString)
GraphQLString)
from py.test import raises from py.test import raises
from graphene.core.fields import (BooleanField, Field, FloatField, IDField, 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 = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field()
f.contribute_to_class(MyOt, 'field_name') f.contribute_to_class(MyOt, 'field_name')
field_type = schema.T(f) 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(): def test_field_resolve_type_custom():

View File

@ -1,7 +1,7 @@
from graphql.core import graphql from graphql import graphql
from graphql.core.type import GraphQLSchema from graphql.type import GraphQLSchema
from graphene.core.fields import Field from graphene.core.fields import Field
from graphene.core.schema import Schema from graphene.core.schema import Schema
@ -40,7 +40,7 @@ Human_type = schema.T(Human)
def test_type(): def test_type():
assert Human._meta.fields_map['name'].resolver( assert Human._meta.fields_map['name'].resolver(
Human(object()), {}, None) == 'Peter' Human(object()), {}, None, None) == 'Peter'
def test_query(): def test_query():
@ -59,6 +59,6 @@ def test_query():
'type': 'Dog' 'type': 'Dog'
} }
} }
result = graphql(schema, query, root=Human(object())) result = graphql(schema, query, root_value=Human(object()))
assert not result.errors assert not result.errors
assert result.data == expected assert result.data == expected

View File

@ -1,4 +1,4 @@
from graphql.core import graphql from graphql import graphql
from py.test import raises from py.test import raises
from graphene import Interface, List, ObjectType, Schema, String from graphene import Interface, List, ObjectType, Schema, String
@ -63,7 +63,7 @@ def test_query_schema_graphql():
'type': 'Dog' 'type': 'Dog'
} }
} }
result = graphql(schema.schema, query, root=Human(object())) result = graphql(schema.schema, query, root_value=Human(object()))
assert not result.errors assert not result.errors
assert result.data == expected assert result.data == expected
@ -84,7 +84,7 @@ def test_query_schema_execute():
'type': 'Dog' 'type': 'Dog'
} }
} }
result = schema.execute(query, root=object()) result = schema.execute(query, root_value=object())
assert not result.errors assert not result.errors
assert result.data == expected assert result.data == expected
@ -93,8 +93,8 @@ def test_schema_get_type_map():
assert_equal_lists( assert_equal_lists(
schema.schema.get_type_map().keys(), schema.schema.get_type_map().keys(),
['__Field', 'String', 'Pet', 'Character', '__InputValue', ['__Field', 'String', 'Pet', 'Character', '__InputValue',
'__Directive', '__TypeKind', '__Schema', '__Type', 'Human', '__Directive', '__DirectiveLocation', '__TypeKind', '__Schema',
'__EnumValue', 'Boolean']) '__Type', 'Human', '__EnumValue', 'Boolean'])
def test_schema_no_query(): def test_schema_no_query():
@ -156,6 +156,10 @@ def test_lazytype():
def test_schema_str(): def test_schema_str():
expected = """ expected = """
schema {
query: Human
}
interface Character { interface Character {
name: String name: String
} }

View File

@ -1,7 +1,7 @@
from functools import wraps from functools import wraps
from itertools import chain from itertools import chain
from graphql.core.type import GraphQLArgument from graphql.type import GraphQLArgument
from ...utils import ProxySnakeDict from ...utils import ProxySnakeDict
from .base import ArgumentType, GroupNamedType, NamedType, OrderedType from .base import ArgumentType, GroupNamedType, NamedType, OrderedType
@ -57,7 +57,7 @@ def to_arguments(*args, **kwargs):
def snake_case_args(resolver): def snake_case_args(resolver):
@wraps(resolver) @wraps(resolver)
def wrapped_resolver(instance, args, info): def wrapped_resolver(instance, args, context, info):
return resolver(instance, ProxySnakeDict(args), info) return resolver(instance, ProxySnakeDict(args), context, info)
return wrapped_resolver return wrapped_resolver

View File

@ -1,7 +1,7 @@
import json import json
import iso8601
from graphql.core.language import ast import iso8601
from graphql.language import ast
from ...core.classtypes.scalar import Scalar from ...core.classtypes.scalar import Scalar

View File

@ -1,5 +1,5 @@
import six import six
from graphql.core.type import GraphQLList, GraphQLNonNull from graphql.type import GraphQLList, GraphQLNonNull
from .base import LazyType, MountedType, MountType from .base import LazyType, MountedType, MountType

View File

@ -2,9 +2,10 @@ from collections import OrderedDict
from functools import wraps from functools import wraps
import six import six
from graphql.core.type import GraphQLField, GraphQLInputObjectField from graphql.type import GraphQLField, GraphQLInputObjectField
from ...utils import maybe_func from ...utils import maybe_func
from ...utils.wrap_resolver_function import wrap_resolver_function
from ..classtypes.base import FieldsClassType from ..classtypes.base import FieldsClassType
from ..classtypes.inputobjecttype import InputObjectType from ..classtypes.inputobjecttype import InputObjectType
from ..classtypes.mutation import Mutation from ..classtypes.mutation import Mutation
@ -105,14 +106,15 @@ class Field(NamedType, OrderedType):
assert len(arguments) == 0 assert len(arguments) == 0
arguments = type_objecttype.get_arguments() arguments = type_objecttype.get_arguments()
resolver = getattr(type_objecttype, 'mutate') resolver = getattr(type_objecttype, 'mutate')
resolver = wrap_resolver_function(resolver)
else: else:
my_resolver = resolver my_resolver = wrap_resolver_function(resolver)
@wraps(my_resolver) @wraps(my_resolver)
def wrapped_func(instance, args, info): def wrapped_func(instance, args, context, info):
if not isinstance(instance, self.object_type): if not isinstance(instance, self.object_type):
instance = self.object_type(_root=instance) instance = self.object_type(_root=instance)
return my_resolver(instance, args, info) return my_resolver(instance, args, context, info)
resolver = wrapped_func resolver = wrapped_func
assert type, 'Internal type for field %s is None' % str(self) assert type, 'Internal type for field %s is None' % str(self)

View File

@ -1,5 +1,5 @@
from graphql.core.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, from graphql.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, GraphQLInt,
GraphQLInt, GraphQLString) GraphQLString)
from .base import MountedType from .base import MountedType

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLArgument from graphql.type import GraphQLArgument
from pytest import raises from pytest import raises
from graphene.core.schema import Schema from graphene.core.schema import Schema
@ -48,7 +48,7 @@ def test_to_arguments_wrong_type():
def test_snake_case_args(): def test_snake_case_args():
def resolver(instance, args, info): def resolver(instance, args, context, info):
return args['my_arg']['inner_arg'] return args['my_arg']['inner_arg']
r = snake_case_args(resolver) r = snake_case_args(resolver)
assert r(None, {'myArg': {'innerArg': 3}}, None) == 3 assert r(None, {'myArg': {'innerArg': 3}}, None, None) == 3

View File

@ -1,6 +1,5 @@
import iso8601 import iso8601
from graphql.language.ast import StringValue
from graphql.core.language.ast import StringValue
from ..custom_scalars import DateTime from ..custom_scalars import DateTime

View File

@ -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 from graphene.core.schema import Schema

View File

@ -1,5 +1,4 @@
from graphql.core.type import (GraphQLField, GraphQLInputObjectField, from graphql.type import GraphQLField, GraphQLInputObjectField, GraphQLString
GraphQLString)
from graphene.core.schema import Schema from graphene.core.schema import Schema
from graphene.core.types import InputObjectType, ObjectType from graphene.core.types import InputObjectType, ObjectType
@ -25,7 +24,7 @@ def test_field_internal_type():
assert field.attname == 'my_field' assert field.attname == 'my_field'
assert isinstance(type, GraphQLField) assert isinstance(type, GraphQLField)
assert type.description == 'My argument' assert type.description == 'My argument'
assert type.resolver(None, {}, None) == 'RESOLVED' assert type.resolver(None, {}, None, None) == 'RESOLVED'
assert type.type == GraphQLString assert type.type == GraphQLString
@ -44,7 +43,7 @@ def test_field_objectype_resolver():
type = schema.T(field) type = schema.T(field)
assert isinstance(type, GraphQLField) assert isinstance(type, GraphQLField)
assert type.description == 'Custom description' assert type.description == 'Custom description'
assert type.resolver(Query(), {}, None) == 'RESOLVED' assert type.resolver(Query(), {}, None, None) == 'RESOLVED'
def test_field_custom_name(): def test_field_custom_name():
@ -143,7 +142,7 @@ def test_field_resolve_argument():
schema = Schema(query=Query) schema = Schema(query=Query)
type = schema.T(field) 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(): def test_field_resolve_vars():
@ -160,7 +159,7 @@ def test_field_resolve_vars():
{ {
hello(firstName:$firstName) hello(firstName:$firstName)
} }
""", args={"firstName": "Serkan"}) """, variable_values={"firstName": "Serkan"})
expected = { expected = {
'hello': 'Hello Serkan' 'hello': 'Hello Serkan'

View File

@ -1,5 +1,5 @@
from graphql.core.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, from graphql.type import (GraphQLBoolean, GraphQLFloat, GraphQLID, GraphQLInt,
GraphQLInt, GraphQLString) GraphQLString)
from graphene.core.schema import Schema from graphene.core.schema import Schema

View File

@ -1,9 +1,11 @@
import six import six
from graphql_relay.node.node import from_global_id from graphql_relay.node.node import from_global_id
from ..core.fields import Field from ..core.fields import Field
from ..core.types.definitions import NonNull from ..core.types.definitions import NonNull
from ..core.types.scalars import ID, Int, String from ..core.types.scalars import ID, Int, String
from ..utils import with_context
class ConnectionField(Field): class ConnectionField(Field):
@ -65,14 +67,13 @@ class NodeField(Field):
object_type or Node, id=id, *args, **kwargs) object_type or Node, id=id, *args, **kwargs)
self.field_object_type = object_type 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 from graphene.relay.utils import is_node
schema = info.schema.graphene_schema schema = info.schema.graphene_schema
try: try:
resolved_global_id = from_global_id(global_id) _type, _id = from_global_id(global_id)
except: except:
return None return None
_type, _id = resolved_global_id.type, resolved_global_id.id
object_type = schema.get_type(_type) object_type = schema.get_type(_type)
if isinstance(self.field_object_type, six.string_types): if isinstance(self.field_object_type, six.string_types):
field_object_type = schema.get_type(self.field_object_type) 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): if not is_node(object_type) or (self.field_object_type and object_type != field_object_type):
return 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') global_id = args.get('id')
return self.id_fetcher(global_id, info) return self.id_fetcher(global_id, context, info)
class GlobalIDField(Field): class GlobalIDField(Field):

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLInputObjectField from graphql.type import GraphQLInputObjectField
import graphene import graphene
from graphene import relay from graphene import relay
@ -76,6 +76,6 @@ def test_execute_mutations():
'result': '5', 'result': '5',
} }
} }
result = schema.execute(query, root=object()) result = schema.execute(query, root_value=object())
assert not result.errors assert not result.errors
assert result.data == expected assert result.data == expected

View File

@ -1,8 +1,8 @@
import pytest import pytest
from graphql.core.type import GraphQLID, GraphQLNonNull from graphql.type import GraphQLID, GraphQLNonNull
import graphene import graphene
from graphene import relay from graphene import relay, with_context
schema = graphene.Schema() schema = graphene.Schema()
@ -24,8 +24,9 @@ class SpecialNode(relay.Node):
value = graphene.String() value = graphene.String()
@classmethod @classmethod
def get_node(cls, id, info): @with_context
value = "!!!" if info.request_context.get('is_special') else "???" def get_node(cls, id, context, info):
value = "!!!" if context.get('is_special') else "???"
return SpecialNode(id=id, value=value) return SpecialNode(id=id, value=value)
@ -108,7 +109,7 @@ def test_get_node_info(specialness, value):
'value': 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 not result.errors
assert result.data == expected assert result.data == expected

View File

@ -1,4 +1,4 @@
from graphql.core.type import GraphQLList from graphql.type import GraphQLList
from pytest import raises from pytest import raises
import graphene import graphene

View File

@ -4,6 +4,7 @@ from collections import Iterable
from functools import wraps from functools import wraps
import six import six
from graphql_relay.connection.arrayconnection import connection_from_list from graphql_relay.connection.arrayconnection import connection_from_list
from graphql_relay.node.node import to_global_id 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.argument import ArgumentsGroup
from ..core.types.definitions import NonNull from ..core.types.definitions import NonNull
from ..utils import memoize from ..utils import memoize
from ..utils.wrap_resolver_function import has_context
from .fields import GlobalIDField from .fields import GlobalIDField
@ -107,7 +109,7 @@ class NodeMeta(InterfaceMeta):
get_node = getattr(cls, 'get_node', None) get_node = getattr(cls, 'get_node', None)
assert get_node, 'get_node classmethod not found in %s Node' % cls assert get_node, 'get_node classmethod not found in %s Node' % cls
assert callable(get_node), 'get_node have to be callable' assert callable(get_node), 'get_node have to be callable'
args = 3 args = 4
if isinstance(get_node, staticmethod): if isinstance(get_node, staticmethod):
args -= 1 args -= 1
@ -119,12 +121,15 @@ class NodeMeta(InterfaceMeta):
@staticmethod @staticmethod
@wraps(get_node) @wraps(get_node)
def wrapped_node(*node_args): def wrapped_node(id, context=None, info=None):
if len(node_args) < args: node_args = [id, info, context]
node_args += (None, ) if has_context(get_node):
return get_node(*node_args[:-1]) return get_node(*node_args[:get_node_num_args - 1], context=context)
if get_node_num_args - 1 == 0:
setattr(cls, 'get_node', wrapped_node) 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): def construct(cls, *args, **kwargs):
cls = super(NodeMeta, cls).construct(*args, **kwargs) cls = super(NodeMeta, cls).construct(*args, **kwargs)

View File

@ -5,8 +5,10 @@ from .maybe_func import maybe_func
from .misc import enum_to_graphql_enum from .misc import enum_to_graphql_enum
from .resolve_only_args import resolve_only_args from .resolve_only_args import resolve_only_args
from .lazylist import LazyList from .lazylist import LazyList
from .wrap_resolver_function import with_context, wrap_resolver_function
__all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict', __all__ = ['to_camel_case', 'to_snake_case', 'to_const', 'ProxySnakeDict',
'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum', 'cached_property', 'memoize', 'maybe_func', 'enum_to_graphql_enum',
'resolve_only_args', 'LazyList'] 'resolve_only_args', 'LazyList', 'with_context',
'wrap_resolver_function']

View File

@ -1,6 +1,6 @@
from collections import OrderedDict from collections import OrderedDict
from graphql.core.type import GraphQLEnumType, GraphQLEnumValue from graphql.type import GraphQLEnumType, GraphQLEnumValue
def enum_to_graphql_enum(enumeration): def enum_to_graphql_enum(enumeration):

View File

@ -1,6 +1,6 @@
import collections import collections
from graphql.core.type import GraphQLEnumType from graphql.type import GraphQLEnumType
from ..misc import enum_to_graphql_enum from ..misc import enum_to_graphql_enum

View File

@ -1,5 +1,5 @@
# coding: utf-8 # 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(): def test_snake_case():

View File

@ -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

View File

@ -24,7 +24,7 @@ class PyTest(TestCommand):
setup( setup(
name='graphene', name='graphene',
version='0.8.1', version='0.8.2',
description='GraphQL Framework for Python', description='GraphQL Framework for Python',
long_description=open('README.rst').read(), long_description=open('README.rst').read(),
@ -55,8 +55,8 @@ setup(
install_requires=[ install_requires=[
'six>=1.10.0', 'six>=1.10.0',
'graphql-core>=0.4.9', 'graphql-core==0.5b3',
'graphql-relay==0.3.3', 'graphql-relay==0.4b1',
'iso8601', 'iso8601',
], ],
tests_require=[ tests_require=[
@ -73,7 +73,7 @@ setup(
'django': [ 'django': [
'Django>=1.6.0', 'Django>=1.6.0',
'singledispatch>=3.4.0.3', 'singledispatch>=3.4.0.3',
'graphql-django-view>=1.1.0', 'graphql-django-view==1.3b1',
], ],
'sqlalchemy': [ 'sqlalchemy': [
'sqlalchemy', 'sqlalchemy',

View File

@ -7,9 +7,9 @@ deps=
pytest>=2.7.2 pytest>=2.7.2
django>=1.8.0,<1.9 django>=1.8.0,<1.9
pytest-django pytest-django
graphql-django-view>=1.0.0 graphql-django-view==1.3b1
graphql-core==0.4.9 graphql-core==0.5b3
graphql-relay==0.3.3 graphql-relay==0.4b1
six six
blinker blinker
singledispatch singledispatch