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