mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-23 01:56:54 +03:00
Merge pull request #159 from graphql-python/core-update
Core update GraphQL-core 0.5.0
This commit is contained in:
commit
3dcb53ac07
|
@ -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
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
from django.test import TestCase
|
|
||||||
|
|
||||||
# Create your tests here.
|
# Create your tests here.
|
||||||
|
|
|
@ -1,3 +1,2 @@
|
||||||
from django.shortcuts import render
|
|
||||||
|
|
||||||
# Create your views here.
|
# Create your views here.
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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()
|
||||||
|
|
|
@ -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)
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -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'])
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
|
||||||
|
|
|
@ -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')
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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'''
|
||||||
|
|
|
@ -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)]
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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():
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
}
|
}
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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'
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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
|
||||||
|
|
|
@ -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)
|
||||||
|
|
|
@ -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']
|
||||||
|
|
|
@ -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):
|
||||||
|
|
|
@ -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
|
||||||
|
|
||||||
|
|
|
@ -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():
|
||||||
|
|
20
graphene/utils/wrap_resolver_function.py
Normal file
20
graphene/utils/wrap_resolver_function.py
Normal 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
|
8
setup.py
8
setup.py
|
@ -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',
|
||||||
|
|
6
tox.ini
6
tox.ini
|
@ -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
|
||||||
|
|
Loading…
Reference in New Issue
Block a user