mirror of
https://github.com/graphql-python/graphene.git
synced 2024-11-22 01:26:49 +03:00
Django integration finished
This commit is contained in:
parent
a55222e107
commit
7073208517
|
@ -1,4 +1,5 @@
|
|||
#!/bin/bash
|
||||
|
||||
autoflake ./ -r --remove-unused-variables --remove-all-unused-imports --in-place
|
||||
autoflake ./ -r --remove-unused-variables --remove-all-unused-imports --in-place
|
||||
autopep8 ./ -r --in-place
|
||||
isort -rc .
|
||||
|
|
|
@ -12,6 +12,7 @@ schema = graphene.Schema(name='Starwars Django Relay Schema')
|
|||
|
||||
|
||||
class Ship(DjangoNode):
|
||||
|
||||
class Meta:
|
||||
model = ShipModel
|
||||
|
||||
|
@ -21,11 +22,13 @@ class Ship(DjangoNode):
|
|||
|
||||
|
||||
class Character(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = CharacterModel
|
||||
|
||||
|
||||
class Faction(DjangoNode):
|
||||
|
||||
class Meta:
|
||||
model = FactionModel
|
||||
|
||||
|
@ -35,6 +38,7 @@ class Faction(DjangoNode):
|
|||
|
||||
|
||||
class IntroduceShip(relay.ClientIDMutation):
|
||||
|
||||
class Input:
|
||||
ship_name = graphene.StringField(required=True)
|
||||
faction_id = graphene.StringField(required=True)
|
||||
|
@ -48,7 +52,7 @@ class IntroduceShip(relay.ClientIDMutation):
|
|||
faction_id = input.get('faction_id')
|
||||
ship = create_ship(ship_name, faction_id)
|
||||
faction = get_faction(faction_id)
|
||||
return IntroduceShip(ship=ship, faction=faction)
|
||||
return IntroduceShip(ship=Ship(ship), faction=Faction(faction))
|
||||
|
||||
|
||||
class Query(graphene.ObjectType):
|
||||
|
|
|
@ -14,7 +14,6 @@ from graphene.core.types import (
|
|||
Mutation,
|
||||
BaseType,
|
||||
LazyType,
|
||||
OrderedType,
|
||||
Argument,
|
||||
Field,
|
||||
InputField,
|
||||
|
@ -28,7 +27,6 @@ from graphene.core.types import (
|
|||
)
|
||||
|
||||
from graphene.core.fields import (
|
||||
Field,
|
||||
StringField,
|
||||
IntField,
|
||||
BooleanField,
|
||||
|
@ -42,7 +40,7 @@ from graphene.decorators import (
|
|||
resolve_only_args
|
||||
)
|
||||
|
||||
__all__ = ['Enum', 'Argument', 'String', 'Int', 'ID', 'signals', 'Schema',
|
||||
'ObjectType', 'Interface', 'Mutation', 'Field', 'StringField',
|
||||
__all__ = ['Enum', 'Argument', 'String', 'Int', 'Boolean', 'Float', 'ID', 'List', 'NonNull', 'signals', 'Schema',
|
||||
'BaseType', 'LazyType', 'ObjectType', 'Interface', 'Mutation', 'Field', 'InputField', 'StringField',
|
||||
'IntField', 'BooleanField', 'IDField', 'ListField', 'NonNullField',
|
||||
'FloatField', 'resolve_only_args']
|
||||
|
|
|
@ -3,9 +3,7 @@ from singledispatch import singledispatch
|
|||
|
||||
from graphene.contrib.django.fields import (ConnectionOrListField,
|
||||
DjangoModelField)
|
||||
from graphene.core.fields import (BooleanField, FloatField, IDField, IntField,
|
||||
StringField)
|
||||
from graphene.core.types.scalars import Boolean, Float, ID, Int, String
|
||||
from graphene.core.types.scalars import ID, Boolean, Float, Int, String
|
||||
|
||||
try:
|
||||
UUIDField = models.UUIDField
|
||||
|
|
|
@ -1,7 +1,9 @@
|
|||
from graphene import relay
|
||||
from graphene.contrib.django.utils import get_type_for_model, lazy_map
|
||||
from graphene.core.fields import Field, ListField
|
||||
from graphene.core.exceptions import SkipField
|
||||
from graphene.core.fields import Field
|
||||
from graphene.core.types.base import FieldType
|
||||
from graphene.core.types.definitions import List
|
||||
from graphene.relay.utils import is_node
|
||||
|
||||
|
||||
|
@ -12,7 +14,10 @@ class DjangoConnectionField(relay.ConnectionField):
|
|||
return lazy_map(value, self.type.get_object_type(schema))
|
||||
|
||||
|
||||
class LazyListField(ListField):
|
||||
class LazyListField(Field):
|
||||
|
||||
def get_type(self, schema):
|
||||
return List(self.type)
|
||||
|
||||
def resolver(self, instance, args, info):
|
||||
schema = info.schema.graphene_schema
|
||||
|
@ -51,6 +56,8 @@ class DjangoModelField(FieldType):
|
|||
self.parent,
|
||||
)
|
||||
)
|
||||
if not _type:
|
||||
raise SkipField()
|
||||
return schema.T(_type)
|
||||
|
||||
def get_object_type(self, schema):
|
||||
|
|
|
@ -1,7 +1,6 @@
|
|||
|
||||
from django.db import models
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
|
||||
import graphene
|
||||
from graphene.contrib.django.converter import convert_django_field
|
|
@ -1,40 +1,21 @@
|
|||
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
|
||||
import graphene
|
||||
from graphene import relay
|
||||
from graphene.contrib.django import DjangoNode, DjangoObjectType
|
||||
from tests.utils import assert_equal_lists
|
||||
|
||||
from .models import Article, Reporter
|
||||
|
||||
|
||||
def test_should_raise_if_no_model():
|
||||
with raises(Exception) as excinfo:
|
||||
class Character1(DjangoObjectType):
|
||||
pass
|
||||
assert 'model in the Meta' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_should_raise_if_model_is_invalid():
|
||||
with raises(Exception) as excinfo:
|
||||
class Character2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = 1
|
||||
assert 'not a Django model' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_should_raise_if_model_is_invalid():
|
||||
with raises(Exception) as excinfo:
|
||||
class ReporterTypeError(DjangoObjectType):
|
||||
def test_should_query_only_fields():
|
||||
with raises(Exception):
|
||||
class ReporterType(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
only_fields = ('articles', )
|
||||
|
||||
schema = graphene.Schema(query=ReporterTypeError)
|
||||
schema = graphene.Schema(query=ReporterType)
|
||||
query = '''
|
||||
query ReporterQuery {
|
||||
articles
|
||||
|
@ -44,24 +25,13 @@ def test_should_raise_if_model_is_invalid():
|
|||
assert not result.errors
|
||||
|
||||
|
||||
def test_should_map_fields_correctly():
|
||||
class ReporterType2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
assert_equal_lists(
|
||||
ReporterType2._meta.fields_map.keys(),
|
||||
['articles', 'first_name', 'last_name', 'email', 'pets', 'id']
|
||||
)
|
||||
|
||||
|
||||
def test_should_map_fields():
|
||||
def test_should_query_well():
|
||||
class ReporterType(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
|
||||
class Query2(graphene.ObjectType):
|
||||
class Query(graphene.ObjectType):
|
||||
reporter = graphene.Field(ReporterType)
|
||||
|
||||
def resolve_reporter(self, *args, **kwargs):
|
||||
|
@ -83,53 +53,41 @@ def test_should_map_fields():
|
|||
'email': ''
|
||||
}
|
||||
}
|
||||
Schema = graphene.Schema(query=Query2)
|
||||
result = Schema.execute(query)
|
||||
schema = graphene.Schema(query=Query)
|
||||
result = schema.execute(query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
||||
|
||||
|
||||
def test_should_map_only_few_fields():
|
||||
class Reporter2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
only_fields = ('id', 'email')
|
||||
assert_equal_lists(
|
||||
Reporter2._meta.fields_map.keys(),
|
||||
['id', 'email']
|
||||
)
|
||||
|
||||
|
||||
def test_should_node():
|
||||
class ReporterNodeType(DjangoNode):
|
||||
class ReporterNode(DjangoNode):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
|
||||
@classmethod
|
||||
def get_node(cls, id):
|
||||
return ReporterNodeType(Reporter(id=2, first_name='Cookie Monster'))
|
||||
return ReporterNode(Reporter(id=2, first_name='Cookie Monster'))
|
||||
|
||||
def resolve_articles(self, *args, **kwargs):
|
||||
return [ArticleNodeType(Article(headline='Hi!'))]
|
||||
return [ArticleNode(Article(headline='Hi!'))]
|
||||
|
||||
class ArticleNodeType(DjangoNode):
|
||||
class ArticleNode(DjangoNode):
|
||||
|
||||
class Meta:
|
||||
model = Article
|
||||
|
||||
@classmethod
|
||||
def get_node(cls, id):
|
||||
return ArticleNodeType(Article(id=1, headline='Article node'))
|
||||
return ArticleNode(Article(id=1, headline='Article node'))
|
||||
|
||||
class Query1(graphene.ObjectType):
|
||||
class Query(graphene.ObjectType):
|
||||
node = relay.NodeField()
|
||||
reporter = graphene.Field(ReporterNodeType)
|
||||
article = graphene.Field(ArticleNodeType)
|
||||
reporter = graphene.Field(ReporterNode)
|
||||
article = graphene.Field(ArticleNode)
|
||||
|
||||
def resolve_reporter(self, *args, **kwargs):
|
||||
return ReporterNodeType(Reporter(id=1, first_name='ABA', last_name='X'))
|
||||
return ReporterNode(Reporter(id=1, first_name='ABA', last_name='X'))
|
||||
|
||||
query = '''
|
||||
query ReporterQuery {
|
||||
|
@ -146,12 +104,12 @@ def test_should_node():
|
|||
lastName,
|
||||
email
|
||||
}
|
||||
myArticle: node(id:"QXJ0aWNsZU5vZGVUeXBlOjE=") {
|
||||
myArticle: node(id:"QXJ0aWNsZU5vZGU6MQ==") {
|
||||
id
|
||||
... on ReporterNodeType {
|
||||
... on ReporterNode {
|
||||
firstName
|
||||
}
|
||||
... on ArticleNodeType {
|
||||
... on ArticleNode {
|
||||
headline
|
||||
}
|
||||
}
|
||||
|
@ -159,7 +117,7 @@ def test_should_node():
|
|||
'''
|
||||
expected = {
|
||||
'reporter': {
|
||||
'id': 'UmVwb3J0ZXJOb2RlVHlwZTox',
|
||||
'id': 'UmVwb3J0ZXJOb2RlOjE=',
|
||||
'firstName': 'ABA',
|
||||
'lastName': 'X',
|
||||
'email': '',
|
||||
|
@ -172,11 +130,11 @@ def test_should_node():
|
|||
},
|
||||
},
|
||||
'myArticle': {
|
||||
'id': 'QXJ0aWNsZU5vZGVUeXBlOjE=',
|
||||
'id': 'QXJ0aWNsZU5vZGU6MQ==',
|
||||
'headline': 'Article node'
|
||||
}
|
||||
}
|
||||
Schema = graphene.Schema(query=Query1)
|
||||
result = Schema.execute(query)
|
||||
schema = graphene.Schema(query=Query)
|
||||
result = schema.execute(query)
|
||||
assert not result.errors
|
||||
assert result.data == expected
|
45
graphene/contrib/django/tests/test_schema.py
Normal file
45
graphene/contrib/django/tests/test_schema.py
Normal file
|
@ -0,0 +1,45 @@
|
|||
from py.test import raises
|
||||
|
||||
from graphene.contrib.django import DjangoObjectType
|
||||
from tests.utils import assert_equal_lists
|
||||
|
||||
from .models import Reporter
|
||||
|
||||
|
||||
def test_should_raise_if_no_model():
|
||||
with raises(Exception) as excinfo:
|
||||
class Character1(DjangoObjectType):
|
||||
pass
|
||||
assert 'model in the Meta' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_should_raise_if_model_is_invalid():
|
||||
with raises(Exception) as excinfo:
|
||||
class Character2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = 1
|
||||
assert 'not a Django model' in str(excinfo.value)
|
||||
|
||||
|
||||
def test_should_map_fields_correctly():
|
||||
class ReporterType2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
assert_equal_lists(
|
||||
ReporterType2._meta.fields_map.keys(),
|
||||
['articles', 'first_name', 'last_name', 'email', 'pets', 'id']
|
||||
)
|
||||
|
||||
|
||||
def test_should_map_only_few_fields():
|
||||
class Reporter2(DjangoObjectType):
|
||||
|
||||
class Meta:
|
||||
model = Reporter
|
||||
only_fields = ('id', 'email')
|
||||
assert_equal_lists(
|
||||
Reporter2._meta.fields_map.keys(),
|
||||
['id', 'email']
|
||||
)
|
|
@ -2,14 +2,16 @@
|
|||
|
||||
from graphene import Schema
|
||||
from graphene.contrib.django.types import DjangoInterface, DjangoNode
|
||||
from graphene.core.fields import IntField, Field
|
||||
from graphene.core.types.scalars import String, Int
|
||||
from graphene.core.fields import Field, IntField
|
||||
from graphene.core.types.scalars import Int
|
||||
from graphene.relay.fields import GlobalIDField
|
||||
from graphql.core.type import GraphQLInterfaceType, GraphQLObjectType
|
||||
from tests.utils import assert_equal_lists
|
||||
|
||||
from .models import Article, Reporter
|
||||
|
||||
schema = Schema()
|
||||
|
||||
|
||||
class Character(DjangoInterface):
|
||||
'''Character description'''
|
||||
|
@ -17,6 +19,7 @@ class Character(DjangoInterface):
|
|||
model = Reporter
|
||||
|
||||
|
||||
@schema.register
|
||||
class Human(DjangoNode):
|
||||
'''Human description'''
|
||||
|
||||
|
@ -28,14 +31,12 @@ class Human(DjangoNode):
|
|||
class Meta:
|
||||
model = Article
|
||||
|
||||
schema = Schema()
|
||||
|
||||
|
||||
def test_django_interface():
|
||||
assert DjangoNode._meta.is_interface is True
|
||||
|
||||
|
||||
def test_pseudo_interface():
|
||||
def test_pseudo_interface_registered():
|
||||
object_type = schema.T(Character)
|
||||
assert Character._meta.is_interface is True
|
||||
assert isinstance(object_type, GraphQLInterfaceType)
|
|
@ -6,7 +6,7 @@ def format_response(response):
|
|||
|
||||
|
||||
def test_client_get_no_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.get('/graphql')
|
||||
json_response = format_response(response)
|
||||
assert json_response == {'errors': [
|
||||
|
@ -14,7 +14,7 @@ def test_client_get_no_query(settings, client):
|
|||
|
||||
|
||||
def test_client_post_no_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.post('/graphql', {})
|
||||
json_response = format_response(response)
|
||||
assert json_response == {'errors': [
|
||||
|
@ -22,7 +22,7 @@ def test_client_post_no_query(settings, client):
|
|||
|
||||
|
||||
def test_client_post_malformed_json(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.post('/graphql', 'MALFORMED', 'application/json')
|
||||
json_response = format_response(response)
|
||||
assert json_response == {'errors': [
|
||||
|
@ -30,7 +30,7 @@ def test_client_post_malformed_json(settings, client):
|
|||
|
||||
|
||||
def test_client_post_empty_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.post(
|
||||
'/graphql', json.dumps({'query': ''}), 'application/json')
|
||||
json_response = format_response(response)
|
||||
|
@ -39,7 +39,7 @@ def test_client_post_empty_query(settings, client):
|
|||
|
||||
|
||||
def test_client_post_bad_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.post(
|
||||
'/graphql', json.dumps({'query': '{ MALFORMED'}), 'application/json')
|
||||
json_response = format_response(response)
|
||||
|
@ -49,7 +49,7 @@ def test_client_post_bad_query(settings, client):
|
|||
|
||||
|
||||
def test_client_get_good_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.get('/graphql', {'query': '{ headline }'})
|
||||
json_response = format_response(response)
|
||||
expected_json = {
|
||||
|
@ -61,7 +61,7 @@ def test_client_get_good_query(settings, client):
|
|||
|
||||
|
||||
def test_client_get_good_query_with_raise(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.get('/graphql', {'query': '{ raises }'})
|
||||
json_response = format_response(response)
|
||||
assert json_response['errors'][0][
|
||||
|
@ -70,7 +70,7 @@ def test_client_get_good_query_with_raise(settings, client):
|
|||
|
||||
|
||||
def test_client_post_good_query(settings, client):
|
||||
settings.ROOT_URLCONF = 'tests.contrib_django.test_urls'
|
||||
settings.ROOT_URLCONF = 'graphene.contrib.django.tests.test_urls'
|
||||
response = client.post(
|
||||
'/graphql', json.dumps({'query': '{ headline }'}), 'application/json')
|
||||
json_response = format_response(response)
|
2
graphene/core/exceptions.py
Normal file
2
graphene/core/exceptions.py
Normal file
|
@ -0,0 +1,2 @@
|
|||
class SkipField(Exception):
|
||||
pass
|
|
@ -1,15 +1,17 @@
|
|||
import warnings
|
||||
|
||||
from .types.base import FieldType
|
||||
from .types.field import Field
|
||||
from .types.scalars import String, Int, Boolean, ID, Float
|
||||
from .types.definitions import List, NonNull
|
||||
from .types.field import Field
|
||||
from .types.scalars import ID, Boolean, Float, Int, String
|
||||
|
||||
|
||||
class DeprecatedField(FieldType):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
cls = self.__class__
|
||||
warnings.warn("Using {} is not longer supported".format(cls.__name__), FutureWarning)
|
||||
warnings.warn("Using {} is not longer supported".format(
|
||||
cls.__name__), FutureWarning)
|
||||
if 'resolve' in kwargs:
|
||||
kwargs['resolver'] = kwargs.pop('resolve')
|
||||
return super(DeprecatedField, self).__init__(*args, **kwargs)
|
||||
|
@ -41,3 +43,7 @@ class ListField(DeprecatedField, List):
|
|||
|
||||
class NonNullField(DeprecatedField, NonNull):
|
||||
pass
|
||||
|
||||
|
||||
__all__ = ['Field', 'StringField', 'IntField', 'BooleanField',
|
||||
'IDField', 'FloatField', 'ListField', 'NonNullField']
|
||||
|
|
|
@ -2,13 +2,13 @@ import inspect
|
|||
from collections import OrderedDict
|
||||
|
||||
from graphene import signals
|
||||
from graphene.core.types.base import BaseType
|
||||
from graphene.core.types.objecttype import BaseObjectType
|
||||
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 graphene.core.types.base import BaseType
|
||||
from graphene.core.types.objecttype import BaseObjectType
|
||||
|
||||
|
||||
class GraphQLSchema(_GraphQLSchema):
|
||||
|
@ -40,7 +40,8 @@ class Schema(object):
|
|||
if object_type not in self._types:
|
||||
internal_type = object_type.internal_type(self)
|
||||
self._types[object_type] = internal_type
|
||||
is_objecttype = inspect.isclass(object_type) and issubclass(object_type, BaseObjectType)
|
||||
is_objecttype = inspect.isclass(
|
||||
object_type) and issubclass(object_type, BaseObjectType)
|
||||
if is_objecttype:
|
||||
self.register(object_type)
|
||||
return self._types[object_type]
|
||||
|
@ -68,7 +69,8 @@ class Schema(object):
|
|||
type_name = object_type._meta.type_name
|
||||
registered_object_type = self._types_names.get(type_name, None)
|
||||
if registered_object_type:
|
||||
assert registered_object_type == object_type, 'Type {} already registered with other object type'.format(type_name)
|
||||
assert registered_object_type == object_type, 'Type {} already registered with other object type'.format(
|
||||
type_name)
|
||||
self._types_names[object_type._meta.type_name] = object_type
|
||||
return object_type
|
||||
|
||||
|
|
|
@ -30,7 +30,7 @@ schema = Schema(query=Query, mutation=MyResultMutation)
|
|||
|
||||
|
||||
def test_mutation_input():
|
||||
assert schema.T(ChangeNumber.arguments).keys() == ['to']
|
||||
assert list(schema.T(ChangeNumber.arguments).keys()) == ['to']
|
||||
|
||||
|
||||
def test_execute_mutations():
|
||||
|
|
|
@ -1,16 +1,16 @@
|
|||
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
|
||||
from graphene.core.fields import Field, NonNullField, StringField
|
||||
from graphene.core.options import Options
|
||||
from graphene.core.fields import (BooleanField, Field, FloatField, IDField,
|
||||
IntField, NonNullField, StringField)
|
||||
from graphene.core.schema import Schema
|
||||
from graphene.core.types import ObjectType
|
||||
from graphql.core.type import (GraphQLBoolean, GraphQLField, GraphQLID,
|
||||
GraphQLInt, GraphQLNonNull, GraphQLString)
|
||||
from graphql.core.type import (GraphQLBoolean, GraphQLField, GraphQLFloat,
|
||||
GraphQLID, GraphQLInt, GraphQLNonNull,
|
||||
GraphQLString)
|
||||
|
||||
|
||||
class ot(ObjectType):
|
||||
class MyOt(ObjectType):
|
||||
|
||||
def resolve_customdoc(self, *args, **kwargs):
|
||||
'''Resolver documentation'''
|
||||
return None
|
||||
|
@ -23,53 +23,77 @@ schema = Schema()
|
|||
|
||||
def test_field_no_contributed_raises_error():
|
||||
f = Field(GraphQLString)
|
||||
with raises(Exception) as excinfo:
|
||||
with raises(Exception):
|
||||
schema.T(f)
|
||||
|
||||
|
||||
def test_field_type():
|
||||
f = Field(GraphQLString)
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert isinstance(schema.T(f), GraphQLField)
|
||||
assert schema.T(f).type == GraphQLString
|
||||
|
||||
|
||||
def test_field_name_automatic_camelcase():
|
||||
f = Field(GraphQLString)
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert f.name == 'fieldName'
|
||||
|
||||
|
||||
def test_field_name_use_name_if_exists():
|
||||
f = Field(GraphQLString, name='my_custom_name')
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert f.name == 'my_custom_name'
|
||||
|
||||
|
||||
def test_stringfield_type():
|
||||
f = StringField()
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert schema.T(f) == GraphQLString
|
||||
|
||||
|
||||
def test_idfield_type():
|
||||
f = IDField()
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert schema.T(f) == GraphQLID
|
||||
|
||||
|
||||
def test_booleanfield_type():
|
||||
f = BooleanField()
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert schema.T(f) == GraphQLBoolean
|
||||
|
||||
|
||||
def test_intfield_type():
|
||||
f = IntField()
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert schema.T(f) == GraphQLInt
|
||||
|
||||
|
||||
def test_floatfield_type():
|
||||
f = FloatField()
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert schema.T(f) == GraphQLFloat
|
||||
|
||||
|
||||
def test_nonnullfield_type():
|
||||
f = NonNullField(StringField())
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert isinstance(schema.T(f), GraphQLNonNull)
|
||||
|
||||
|
||||
def test_stringfield_type_required():
|
||||
f = StringField(required=True).as_field()
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert isinstance(schema.T(f), GraphQLField)
|
||||
assert isinstance(schema.T(f).type, GraphQLNonNull)
|
||||
|
||||
|
||||
def test_field_resolve():
|
||||
f = StringField(required=True, resolve=lambda *args: 'RESOLVED').as_field()
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
field_type = schema.T(f)
|
||||
assert 'RESOLVED' == field_type.resolver(ot, None, None)
|
||||
assert 'RESOLVED' == field_type.resolver(MyOt, None, None)
|
||||
|
||||
|
||||
def test_field_resolve_type_custom():
|
||||
|
@ -123,17 +147,17 @@ def test_field_hash():
|
|||
def test_field_none_type_raises_error():
|
||||
s = Schema()
|
||||
f = Field(None)
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
with raises(Exception) as excinfo:
|
||||
s.T(f)
|
||||
assert str(
|
||||
excinfo.value) == "Internal type for field ot.field_name is None"
|
||||
excinfo.value) == "Internal type for field MyOt.field_name is None"
|
||||
|
||||
|
||||
def test_field_str():
|
||||
f = StringField().as_field()
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
assert str(f) == "ot.field_name"
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert str(f) == "MyOt.field_name"
|
||||
|
||||
|
||||
def test_field_repr():
|
||||
|
@ -143,12 +167,12 @@ def test_field_repr():
|
|||
|
||||
def test_field_repr_contributed():
|
||||
f = StringField().as_field()
|
||||
f.contribute_to_class(ot, 'field_name')
|
||||
f.contribute_to_class(MyOt, 'field_name')
|
||||
assert repr(f) == "<graphene.core.types.field.Field: field_name>"
|
||||
|
||||
|
||||
def test_field_resolve_objecttype_cos():
|
||||
f = StringField().as_field()
|
||||
f.contribute_to_class(ot, 'customdoc')
|
||||
f.contribute_to_class(MyOt, 'customdoc')
|
||||
field = schema.T(f)
|
||||
assert field.description == 'Resolver documentation'
|
|
@ -1,6 +1,4 @@
|
|||
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
|
||||
from graphene.core.fields import StringField
|
||||
from graphene.core.options import Options
|
||||
|
|
|
@ -1,13 +1,9 @@
|
|||
|
||||
from py.test import raises
|
||||
from pytest import raises
|
||||
|
||||
from graphene import Interface, ObjectType, Schema
|
||||
from graphene.core.fields import Field, ListField, StringField
|
||||
from graphene.core.types.base import LazyType
|
||||
from graphql.core import graphql
|
||||
from graphql.core.type import (GraphQLInterfaceType, GraphQLObjectType,
|
||||
GraphQLSchema)
|
||||
from tests.utils import assert_equal_lists
|
||||
|
||||
schema = Schema(name='My own schema')
|
||||
|
|
|
@ -1,6 +1,9 @@
|
|||
from .objecttype import ObjectTypeMeta, BaseObjectType, ObjectType, Interface, Mutation, InputObjectType
|
||||
from .base import BaseType, LazyType, OrderedType
|
||||
from .argument import Argument
|
||||
from .field import Field, InputField
|
||||
from .scalars import String, Int, Boolean, ID, Float
|
||||
from .argument import Argument, ArgumentsGroup, to_arguments
|
||||
from .definitions import List, NonNull
|
||||
from .objecttype import ObjectTypeMeta, BaseObjectType, Interface, ObjectType, Mutation, InputObjectType
|
||||
from .scalars import String, ID, Boolean, Int, Float, Scalar
|
||||
from .field import Field, InputField
|
||||
|
||||
__all__ = ['BaseType', 'LazyType', 'OrderedType', 'Argument', 'ArgumentsGroup', 'to_arguments', 'List', 'NonNull', 'Field', 'InputField',
|
||||
'Interface', 'BaseObjectType', 'ObjectTypeMeta', 'ObjectType', 'Mutation', 'InputObjectType', 'String', 'ID', 'Boolean', 'Int', 'Float', 'Scalar']
|
||||
|
|
|
@ -3,11 +3,12 @@ from itertools import chain
|
|||
|
||||
from graphql.core.type import GraphQLArgument
|
||||
|
||||
from .base import BaseType, OrderedType, ArgumentType
|
||||
from ...utils import to_camel_case
|
||||
from .base import ArgumentType, BaseType, OrderedType
|
||||
|
||||
|
||||
class Argument(OrderedType):
|
||||
|
||||
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None):
|
||||
super(Argument, self).__init__(_creation_counter=_creation_counter)
|
||||
self.name = name
|
||||
|
@ -23,6 +24,7 @@ class Argument(OrderedType):
|
|||
|
||||
|
||||
class ArgumentsGroup(BaseType):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
arguments = to_arguments(*args, **kwargs)
|
||||
self.arguments = OrderedDict([(arg.name, arg) for arg in arguments])
|
||||
|
@ -58,7 +60,8 @@ def to_arguments(*args, **kwargs):
|
|||
if name:
|
||||
argument.name = to_camel_case(name)
|
||||
assert argument.name, 'Argument in field must have a name'
|
||||
assert argument.name not in arguments, 'Found more than one Argument with same name {}'.format(argument.name)
|
||||
assert argument.name not in arguments, 'Found more than one Argument with same name {}'.format(
|
||||
argument.name)
|
||||
arguments[argument.name] = argument
|
||||
|
||||
return sorted(arguments.values())
|
||||
|
|
|
@ -1,8 +1,10 @@
|
|||
import six
|
||||
from functools import total_ordering
|
||||
|
||||
import six
|
||||
|
||||
|
||||
class BaseType(object):
|
||||
|
||||
@classmethod
|
||||
def internal_type(cls, schema):
|
||||
return getattr(cls, 'T', None)
|
||||
|
@ -16,6 +18,7 @@ class MountType(BaseType):
|
|||
|
||||
|
||||
class LazyType(MountType):
|
||||
|
||||
def __init__(self, type):
|
||||
self.type = type
|
||||
|
||||
|
@ -57,13 +60,13 @@ class OrderedType(MountType):
|
|||
|
||||
def __lt__(self, other):
|
||||
# This is needed because bisect does not take a comparison function.
|
||||
if type(self) == type(other):
|
||||
if isinstance(other, OrderedType):
|
||||
return self.creation_counter < other.creation_counter
|
||||
return NotImplemented
|
||||
|
||||
def __gt__(self, other):
|
||||
# This is needed because bisect does not take a comparison function.
|
||||
if type(self) == type(other):
|
||||
if isinstance(other, OrderedType):
|
||||
return self.creation_counter > other.creation_counter
|
||||
return NotImplemented
|
||||
|
||||
|
@ -72,6 +75,7 @@ class OrderedType(MountType):
|
|||
|
||||
|
||||
class MirroredType(OrderedType):
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
_creation_counter = kwargs.pop('_creation_counter', None)
|
||||
super(MirroredType, self).__init__(_creation_counter=_creation_counter)
|
||||
|
@ -80,12 +84,14 @@ class MirroredType(OrderedType):
|
|||
|
||||
|
||||
class ArgumentType(MirroredType):
|
||||
|
||||
def as_argument(self):
|
||||
from .argument import Argument
|
||||
return Argument(self, _creation_counter=self.creation_counter, *self.args, **self.kwargs)
|
||||
|
||||
|
||||
class FieldType(MirroredType):
|
||||
|
||||
def contribute_to_class(self, cls, name):
|
||||
from ..types import BaseObjectType, InputObjectType
|
||||
if issubclass(cls, InputObjectType):
|
||||
|
|
|
@ -1,12 +1,14 @@
|
|||
import six
|
||||
from graphql.core.type import (GraphQLList, GraphQLNonNull)
|
||||
|
||||
from .base import MountType, MountedType, LazyType
|
||||
from graphql.core.type import GraphQLList, GraphQLNonNull
|
||||
|
||||
from .base import LazyType, MountedType, MountType
|
||||
|
||||
|
||||
class OfType(MountedType):
|
||||
|
||||
def __init__(self, of_type, *args, **kwargs):
|
||||
if isinstance(of_type, six.string_types) and of_type != 'self':
|
||||
if isinstance(of_type, six.string_types):
|
||||
of_type = LazyType(of_type)
|
||||
self.of_type = of_type
|
||||
super(OfType, self).__init__(*args, **kwargs)
|
||||
|
|
|
@ -1,14 +1,15 @@
|
|||
import six
|
||||
from collections import OrderedDict
|
||||
from functools import wraps
|
||||
|
||||
import six
|
||||
|
||||
from graphql.core.type import GraphQLField, GraphQLInputObjectField
|
||||
|
||||
from .base import MountType, LazyType, OrderedType
|
||||
from .argument import ArgumentsGroup
|
||||
from .definitions import NonNull
|
||||
from ...utils import to_camel_case, ProxySnakeDict
|
||||
from ...utils import ProxySnakeDict, to_camel_case
|
||||
from ..types import BaseObjectType, InputObjectType
|
||||
from .argument import ArgumentsGroup
|
||||
from .base import LazyType, MountType, OrderedType
|
||||
from .definitions import NonNull
|
||||
|
||||
|
||||
def make_args_snake_case(resolver):
|
||||
|
@ -24,6 +25,7 @@ class Empty(object):
|
|||
|
||||
|
||||
class Field(OrderedType):
|
||||
|
||||
def __init__(self, type, description=None, args=None, name=None, resolver=None, required=False, default=None, *args_list, **kwargs):
|
||||
_creation_counter = kwargs.pop('_creation_counter', None)
|
||||
super(Field, self).__init__(_creation_counter=_creation_counter)
|
||||
|
@ -40,7 +42,8 @@ class Field(OrderedType):
|
|||
self.default = default
|
||||
|
||||
def contribute_to_class(self, cls, attname):
|
||||
assert issubclass(cls, BaseObjectType), 'Field {} cannot be mounted in {}'.format(self, cls)
|
||||
assert issubclass(
|
||||
cls, BaseObjectType), 'Field {} cannot be mounted in {}'.format(self, cls)
|
||||
if not self.name:
|
||||
self.name = to_camel_case(attname)
|
||||
self.attname = attname
|
||||
|
@ -104,11 +107,18 @@ class Field(OrderedType):
|
|||
""" Return "object_type.field_name". """
|
||||
return '%s.%s' % (self.object_type.__name__, self.attname)
|
||||
|
||||
def __eq__(self, other):
|
||||
eq = super(Field, self).__eq__(other)
|
||||
if type(self) == type(other):
|
||||
return eq and self.object_type == other.object_type
|
||||
return NotImplemented
|
||||
|
||||
def __hash__(self):
|
||||
return hash((self.creation_counter, self.object_type))
|
||||
|
||||
|
||||
class InputField(OrderedType):
|
||||
|
||||
def __init__(self, type, description=None, default=None, name=None, _creation_counter=None, required=False):
|
||||
super(InputField, self).__init__(_creation_counter=_creation_counter)
|
||||
self.name = name
|
||||
|
@ -119,7 +129,8 @@ class InputField(OrderedType):
|
|||
self.default = default
|
||||
|
||||
def contribute_to_class(self, cls, attname):
|
||||
assert issubclass(cls, InputObjectType), 'InputField {} cannot be mounted in {}'.format(self, cls)
|
||||
assert issubclass(
|
||||
cls, InputObjectType), 'InputField {} cannot be mounted in {}'.format(self, cls)
|
||||
if not self.name:
|
||||
self.name = to_camel_case(attname)
|
||||
self.attname = attname
|
||||
|
|
|
@ -6,9 +6,10 @@ from functools import partial
|
|||
import six
|
||||
|
||||
from graphene import signals
|
||||
from graphene.core.exceptions import SkipField
|
||||
from graphene.core.options import Options
|
||||
from graphene.core.types.base import BaseType
|
||||
from graphene.core.types.argument import ArgumentsGroup
|
||||
from graphene.core.types.base import BaseType
|
||||
from graphql.core.type import (GraphQLArgument, GraphQLInputObjectType,
|
||||
GraphQLInterfaceType, GraphQLObjectType)
|
||||
|
||||
|
@ -176,23 +177,32 @@ class BaseObjectType(BaseType):
|
|||
|
||||
@classmethod
|
||||
def internal_type(cls, schema):
|
||||
fields = lambda: OrderedDict([(f.name, schema.T(f))
|
||||
for f in cls._meta.fields])
|
||||
if cls._meta.is_interface:
|
||||
return GraphQLInterfaceType(
|
||||
cls._meta.type_name,
|
||||
description=cls._meta.description,
|
||||
resolve_type=partial(cls.resolve_type, schema),
|
||||
fields=fields
|
||||
fields=partial(cls.get_fields, schema)
|
||||
)
|
||||
return GraphQLObjectType(
|
||||
cls._meta.type_name,
|
||||
description=cls._meta.description,
|
||||
interfaces=[schema.T(i) for i in cls._meta.interfaces],
|
||||
fields=fields,
|
||||
fields=partial(cls.get_fields, schema),
|
||||
is_type_of=getattr(cls, 'is_type_of', None)
|
||||
)
|
||||
|
||||
@classmethod
|
||||
def get_fields(cls, schema):
|
||||
fields = []
|
||||
for field in cls._meta.fields:
|
||||
try:
|
||||
fields.append((field.name, schema.T(field)))
|
||||
except SkipField:
|
||||
continue
|
||||
|
||||
return OrderedDict(fields)
|
||||
|
||||
|
||||
class Interface(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
||||
pass
|
||||
|
@ -203,14 +213,16 @@ class ObjectType(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
|||
|
||||
|
||||
class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
||||
|
||||
@classmethod
|
||||
def _prepare_class(cls):
|
||||
input_class = getattr(cls, 'Input', None)
|
||||
if input_class:
|
||||
items = dict(input_class.__dict__)
|
||||
items = dict(vars(input_class))
|
||||
items.pop('__dict__', None)
|
||||
items.pop('__doc__', None)
|
||||
items.pop('__module__', None)
|
||||
items.pop('__weakref__', None)
|
||||
arguments = ArgumentsGroup(**items)
|
||||
cls.add_to_class('arguments', arguments)
|
||||
delattr(cls, 'Input')
|
||||
|
@ -221,6 +233,7 @@ class Mutation(six.with_metaclass(ObjectTypeMeta, BaseObjectType)):
|
|||
|
||||
|
||||
class InputObjectType(ObjectType):
|
||||
|
||||
@classmethod
|
||||
def internal_type(cls, schema):
|
||||
fields = lambda: OrderedDict([(f.name, schema.T(f))
|
||||
|
|
|
@ -25,6 +25,7 @@ class Float(MountedType):
|
|||
|
||||
|
||||
class Scalar(MountedType):
|
||||
|
||||
@classmethod
|
||||
def internal_type(cls, schema):
|
||||
serialize = getattr(cls, 'serialize')
|
||||
|
|
|
@ -1,10 +1,11 @@
|
|||
from pytest import raises
|
||||
|
||||
from graphene.core.schema import Schema
|
||||
from graphene.core.types import ObjectType
|
||||
from graphql.core.type import GraphQLArgument
|
||||
|
||||
from ..argument import Argument, to_arguments
|
||||
from ..scalars import String
|
||||
from graphene.core.types import ObjectType
|
||||
from graphene.core.schema import Schema
|
||||
|
||||
|
||||
def test_argument_internal_type():
|
||||
|
@ -26,7 +27,8 @@ def test_to_arguments():
|
|||
other_kwarg=String(),
|
||||
)
|
||||
|
||||
assert [a.name for a in arguments] == ['myArg', 'otherArg', 'myKwarg', 'otherKwarg']
|
||||
assert [a.name for a in arguments] == [
|
||||
'myArg', 'otherArg', 'myKwarg', 'otherKwarg']
|
||||
|
||||
|
||||
def test_to_arguments_no_name():
|
||||
|
|
|
@ -1,9 +1,10 @@
|
|||
from mock import patch
|
||||
|
||||
from ..base import OrderedType, MountedType
|
||||
from ..field import Field, InputField
|
||||
from graphene.core.types import InputObjectType, ObjectType
|
||||
|
||||
from ..argument import Argument
|
||||
from graphene.core.types import ObjectType, InputObjectType
|
||||
from ..base import MountedType, OrderedType
|
||||
from ..field import Field, InputField
|
||||
|
||||
|
||||
def test_orderedtype_equal():
|
||||
|
@ -26,14 +27,16 @@ def test_type_as_field_called(Field):
|
|||
resolver = lambda x: x
|
||||
a = MountedType(2, description='A', resolver=resolver)
|
||||
a.as_field()
|
||||
Field.assert_called_with(a, 2, _creation_counter=a.creation_counter, description='A', resolver=resolver)
|
||||
Field.assert_called_with(
|
||||
a, 2, _creation_counter=a.creation_counter, description='A', resolver=resolver)
|
||||
|
||||
|
||||
@patch('graphene.core.types.argument.Argument')
|
||||
def test_type_as_argument_called(Argument):
|
||||
a = MountedType(2, description='A')
|
||||
a.as_argument()
|
||||
Argument.assert_called_with(a, 2, _creation_counter=a.creation_counter, description='A')
|
||||
Argument.assert_called_with(
|
||||
a, 2, _creation_counter=a.creation_counter, description='A')
|
||||
|
||||
|
||||
def test_type_as_field():
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from graphql.core.type import (GraphQLList, GraphQLString, GraphQLNonNull)
|
||||
from graphene.core.schema import Schema
|
||||
from graphql.core.type import GraphQLList, GraphQLNonNull, GraphQLString
|
||||
|
||||
from ..definitions import List, NonNull
|
||||
from ..scalars import String
|
||||
from graphene.core.schema import Schema
|
||||
|
||||
schema = Schema()
|
||||
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
from graphql.core.type import GraphQLField, GraphQLInputObjectField, GraphQLString
|
||||
from graphene.core.schema import Schema
|
||||
from graphene.core.types import InputObjectType, ObjectType
|
||||
from graphql.core.type import (GraphQLField, GraphQLInputObjectField,
|
||||
GraphQLString)
|
||||
|
||||
from ..field import Field, InputField
|
||||
from ..scalars import String
|
||||
from ..base import LazyType
|
||||
from ..definitions import List
|
||||
from graphene.core.types import ObjectType, InputObjectType
|
||||
from graphene.core.schema import Schema
|
||||
from ..field import Field, InputField
|
||||
from ..scalars import String
|
||||
|
||||
|
||||
def test_field_internal_type():
|
||||
|
@ -81,8 +82,10 @@ def test_field_string_reference():
|
|||
class MyObjectType(ObjectType):
|
||||
my_field = field
|
||||
|
||||
schema = Schema(query=MyObjectType)
|
||||
|
||||
assert isinstance(field.type, LazyType)
|
||||
assert field.type.type_str == 'MyObjectType'
|
||||
assert schema.T(field.type) == schema.T(MyObjectType)
|
||||
|
||||
|
||||
def test_field_custom_arguments():
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from graphene.core.schema import Schema
|
||||
from graphql.core.type import (GraphQLBoolean, GraphQLFloat, GraphQLID,
|
||||
GraphQLInt, GraphQLScalarType, GraphQLString)
|
||||
|
||||
from ..scalars import String, Int, Boolean, ID, Float, Scalar
|
||||
from graphene.core.schema import Schema
|
||||
from ..scalars import ID, Boolean, Float, Int, Scalar, String
|
||||
|
||||
schema = Schema()
|
||||
|
||||
|
|
|
@ -1,8 +1,7 @@
|
|||
from collections import Iterable
|
||||
|
||||
from graphene.core.fields import Field, IDField
|
||||
from graphene.core.types.scalars import String, ID, Int
|
||||
from graphql.core.type import GraphQLArgument, GraphQLID, GraphQLNonNull
|
||||
from graphene.core.fields import Field
|
||||
from graphene.core.types.scalars import ID, Int, String
|
||||
from graphql_relay.connection.arrayconnection import connection_from_list
|
||||
from graphql_relay.node.node import from_global_id
|
||||
|
||||
|
@ -23,7 +22,6 @@ class ConnectionField(Field):
|
|||
def wrap_resolved(self, value, instance, args, info):
|
||||
return value
|
||||
|
||||
|
||||
def resolver(self, instance, args, info):
|
||||
from graphene.relay.types import PageInfo
|
||||
schema = info.schema.graphene_schema
|
||||
|
@ -59,7 +57,7 @@ class ConnectionField(Field):
|
|||
assert is_node(node), 'Only nodes have connections.'
|
||||
schema.register(node)
|
||||
connection_type = self.get_connection_type(node)
|
||||
return schema.T(connection_type)
|
||||
return connection_type
|
||||
|
||||
|
||||
class NodeField(Field):
|
||||
|
@ -67,7 +65,8 @@ class NodeField(Field):
|
|||
def __init__(self, object_type=None, *args, **kwargs):
|
||||
from graphene.relay.types import Node
|
||||
id = kwargs.pop('id', None) or ID(description='The ID of an object')
|
||||
super(NodeField, self).__init__(object_type or Node, id=id, *args, **kwargs)
|
||||
super(NodeField, self).__init__(
|
||||
object_type or Node, id=id, *args, **kwargs)
|
||||
self.field_object_type = object_type
|
||||
|
||||
def id_fetcher(self, global_id, info):
|
||||
|
@ -89,6 +88,7 @@ class NodeField(Field):
|
|||
|
||||
class GlobalIDField(Field):
|
||||
'''The ID of an object'''
|
||||
|
||||
def __init__(self, *args, **kwargs):
|
||||
super(GlobalIDField, self).__init__(ID(), *args, **kwargs)
|
||||
self.required = True
|
||||
|
@ -100,4 +100,4 @@ class GlobalIDField(Field):
|
|||
super(GlobalIDField, self).contribute_to_class(cls, name)
|
||||
|
||||
def resolver(self, instance, args, info):
|
||||
return self.object_type.to_global_id(instance, args, info)
|
||||
return instance.to_global_id()
|
||||
|
|
0
graphene/relay/tests/__init__.py
Normal file
0
graphene/relay/tests/__init__.py
Normal file
|
@ -1,8 +1,6 @@
|
|||
import graphene
|
||||
from graphene import relay
|
||||
from graphene.core.schema import Schema
|
||||
from graphene.core.types import InputObjectType
|
||||
from graphql.core.type import GraphQLInputObjectField
|
||||
|
||||
my_id = 0
|
||||
|
||||
|
@ -35,7 +33,7 @@ schema = Schema(query=Query, mutation=MyResultMutation)
|
|||
def test_mutation_arguments():
|
||||
assert ChangeNumber.arguments
|
||||
assert list(ChangeNumber.arguments) == ['input']
|
||||
_input = ChangeNumber.arguments['input']
|
||||
ChangeNumber.arguments['input']
|
||||
|
||||
# inner_type = _input.get_object_type(schema)
|
||||
# client_mutation_id_field = inner_type._meta.fields_map[
|
||||
|
|
|
@ -1,8 +1,8 @@
|
|||
from graphene.core.fields import BooleanField, Field, ListField, StringField
|
||||
from graphene.core.types import (InputObjectType, Interface, Mutation,
|
||||
ObjectType)
|
||||
from graphene.core.types.base import LazyType
|
||||
from graphene.core.types.argument import ArgumentsGroup
|
||||
from graphene.core.types.base import LazyType
|
||||
from graphene.core.types.definitions import NonNull
|
||||
from graphene.relay.fields import GlobalIDField
|
||||
from graphene.utils import memoize
|
||||
|
@ -74,10 +74,9 @@ class BaseNode(object):
|
|||
assert hasattr(
|
||||
cls, 'get_node'), 'get_node classmethod not found in %s Node' % cls
|
||||
|
||||
@classmethod
|
||||
def to_global_id(cls, instance, args, info):
|
||||
type_name = cls._meta.type_name
|
||||
return to_global_id(type_name, instance.id)
|
||||
def to_global_id(self):
|
||||
type_name = self._meta.type_name
|
||||
return to_global_id(type_name, self.id)
|
||||
|
||||
connection_type = Connection
|
||||
edge_type = Edge
|
||||
|
@ -105,13 +104,16 @@ class ClientIDMutation(Mutation):
|
|||
|
||||
@classmethod
|
||||
def _prepare_class(cls):
|
||||
Input = getattr(cls, 'Input', None)
|
||||
if Input:
|
||||
input_class = getattr(cls, 'Input', None)
|
||||
if input_class:
|
||||
assert hasattr(
|
||||
cls, 'mutate_and_get_payload'), 'You have to implement mutate_and_get_payload'
|
||||
|
||||
items = dict(Input.__dict__)
|
||||
items = dict(vars(input_class))
|
||||
items.pop('__dict__', None)
|
||||
items.pop('__doc__', None)
|
||||
items.pop('__module__', None)
|
||||
items.pop('__weakref__', None)
|
||||
new_input_type = type('{}Input'.format(
|
||||
cls._meta.type_name), (MutationInputType, ), items)
|
||||
cls.add_to_class('input_type', new_input_type)
|
||||
|
|
|
@ -2,7 +2,6 @@ SECRET_KEY = 1
|
|||
|
||||
INSTALLED_APPS = [
|
||||
'examples.starwars_django',
|
||||
'tests.contrib_django',
|
||||
]
|
||||
|
||||
DATABASES = {
|
||||
|
|
Loading…
Reference in New Issue
Block a user