mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-22 09:36:44 +03:00
Added support for graphql 0.5.0
This commit is contained in:
parent
76ea7d7637
commit
c738d3db28
|
@ -25,6 +25,8 @@ 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 https://github.com/graphql-python/graphql-core/archive/master.zip
|
||||
pip install https://github.com/graphql-python/graphql-relay-py/archive/master.zip
|
||||
pip install --download-cache $HOME/.cache/pip/ -e .[django]
|
||||
pip install --download-cache $HOME/.cache/pip/ -e .[sqlalchemy]
|
||||
pip install django==$DJANGO_VERSION
|
||||
|
|
|
@ -33,7 +33,8 @@ from graphene.core.fields import (
|
|||
)
|
||||
|
||||
from graphene.utils import (
|
||||
resolve_only_args
|
||||
resolve_only_args,
|
||||
with_context
|
||||
)
|
||||
|
||||
__all__ = [
|
||||
|
|
|
@ -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()
|
||||
|
|
|
@ -149,6 +149,7 @@ def test_should_query_connection():
|
|||
schema = graphene.Schema(query=Query, plugins=[DjangoDebugPlugin()])
|
||||
result = schema.execute(query)
|
||||
assert not result.errors
|
||||
print result.data['__debug']['sql']
|
||||
assert result.data['allReporters'] == expected['allReporters']
|
||||
assert 'COUNT' in result.data['__debug']['sql'][0]['rawSql']
|
||||
query = str(Reporter.objects.all()[:1].query)
|
||||
|
|
|
@ -14,15 +14,15 @@ 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)
|
||||
|
||||
|
||||
|
|
|
@ -16,13 +16,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'])
|
||||
|
||||
|
|
|
@ -11,6 +11,3 @@ class GraphQLView(BaseGraphQLView):
|
|||
executor=schema.executor,
|
||||
**kwargs
|
||||
)
|
||||
|
||||
def execute(self, *args, **kwargs):
|
||||
return self.graphene_schema.execute(*args, **kwargs)
|
||||
|
|
|
@ -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)]
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
import inspect
|
||||
from collections import OrderedDict
|
||||
|
||||
from graphql.execution.executors.sync import SyncExecutor
|
||||
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
|
||||
|
@ -116,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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -94,7 +94,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():
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
}
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -5,6 +5,7 @@ import six
|
|||
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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -25,7 +25,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 +44,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 +143,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 +160,7 @@ def test_field_resolve_vars():
|
|||
{
|
||||
hello(firstName:$firstName)
|
||||
}
|
||||
""", args={"firstName": "Serkan"})
|
||||
""", variable_values={"firstName": "Serkan"})
|
||||
|
||||
expected = {
|
||||
'hello': 'Hello Serkan'
|
||||
|
|
|
@ -4,7 +4,7 @@ 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 +65,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)
|
||||
|
@ -83,9 +82,10 @@ class NodeField(Field):
|
|||
|
||||
return object_type.get_node(_id, 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):
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -2,7 +2,7 @@ import pytest
|
|||
from graphql.type import GraphQLID, GraphQLNonNull
|
||||
|
||||
import graphene
|
||||
from graphene import relay
|
||||
from graphene import relay, with_context
|
||||
|
||||
schema = graphene.Schema()
|
||||
|
||||
|
@ -16,7 +16,7 @@ class MyNode(relay.Node):
|
|||
name = graphene.String()
|
||||
|
||||
@classmethod
|
||||
def get_node(cls, id, info):
|
||||
def get_node(cls, id, context, info):
|
||||
return MyNode(id=id, name='mo')
|
||||
|
||||
|
||||
|
@ -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
|
||||
|
||||
|
|
|
@ -14,6 +14,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 wrap_resolver_function
|
||||
from .fields import GlobalIDField
|
||||
|
||||
|
||||
|
|
|
@ -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']
|
||||
|
|
17
graphene/utils/wrap_resolver_function.py
Normal file
17
graphene/utils/wrap_resolver_function.py
Normal file
|
@ -0,0 +1,17 @@
|
|||
from functools import wraps
|
||||
|
||||
|
||||
def with_context(func):
|
||||
setattr(func, 'with_context', 'context')
|
||||
return func
|
||||
|
||||
|
||||
def wrap_resolver_function(func):
|
||||
@wraps(func)
|
||||
def inner(self, args, context, info):
|
||||
with_context = getattr(func, 'with_context', None)
|
||||
if with_context:
|
||||
return func(self, args, context, info)
|
||||
# For old compatibility
|
||||
return func(self, args, info)
|
||||
return inner
|
Loading…
Reference in New Issue
Block a user