mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-11-04 01:47:45 +03:00 
			
		
		
		
	Updated SQLAlchemy code to work with latest version of graphene.
This commit is contained in:
		
							parent
							
								
									c414b3f688
								
							
						
					
					
						commit
						f296a2a73f
					
				| 
						 | 
					@ -1,33 +1,35 @@
 | 
				
			||||||
import graphene
 | 
					import graphene
 | 
				
			||||||
from graphene import relay
 | 
					from graphene import relay
 | 
				
			||||||
from graphene_sqlalchemy import (SQLAlchemyConnectionField,
 | 
					from graphene_sqlalchemy import (SQLAlchemyConnectionField,
 | 
				
			||||||
                                 SQLAlchemyObjectType,
 | 
					                                 SQLAlchemyObjectType)
 | 
				
			||||||
                                 SQLAlchemyNode)
 | 
					 | 
				
			||||||
from models import Department as DepartmentModel
 | 
					from models import Department as DepartmentModel
 | 
				
			||||||
from models import Employee as EmployeeModel
 | 
					from models import Employee as EmployeeModel
 | 
				
			||||||
from models import Role as RoleModel
 | 
					from models import Role as RoleModel
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Department(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					class Department(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = DepartmentModel
 | 
					        model = DepartmentModel
 | 
				
			||||||
 | 
					        interfaces = (relay.Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Employee(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					class Employee(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = EmployeeModel
 | 
					        model = EmployeeModel
 | 
				
			||||||
 | 
					        interfaces = (relay.Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Role(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					class Role(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = RoleModel
 | 
					        model = RoleModel
 | 
				
			||||||
 | 
					        interfaces = (relay.Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Query(graphene.ObjectType):
 | 
					class Query(graphene.ObjectType):
 | 
				
			||||||
    node = SQLAlchemyNode.Field()
 | 
					    node = relay.Node.Field()
 | 
				
			||||||
    all_employees = SQLAlchemyConnectionField(Employee)
 | 
					    all_employees = SQLAlchemyConnectionField(Employee)
 | 
				
			||||||
    all_roles = SQLAlchemyConnectionField(Role)
 | 
					    all_roles = SQLAlchemyConnectionField(Role)
 | 
				
			||||||
    role = graphene.Field(Role)
 | 
					    role = graphene.Field(Role)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,9 @@
 | 
				
			||||||
from .types import (
 | 
					from .types import (
 | 
				
			||||||
    SQLAlchemyObjectType,
 | 
					    SQLAlchemyObjectType,
 | 
				
			||||||
    SQLAlchemyNode
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
from .fields import (
 | 
					from .fields import (
 | 
				
			||||||
    SQLAlchemyConnectionField
 | 
					    SQLAlchemyConnectionField
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
__all__ = ['SQLAlchemyObjectType', 'SQLAlchemyNode',
 | 
					__all__ = ['SQLAlchemyObjectType',
 | 
				
			||||||
           'SQLAlchemyConnectionField']
 | 
					           'SQLAlchemyConnectionField']
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,8 @@ from sqlalchemy import types
 | 
				
			||||||
from sqlalchemy.orm import interfaces
 | 
					from sqlalchemy.orm import interfaces
 | 
				
			||||||
from sqlalchemy.dialects import postgresql
 | 
					from sqlalchemy.dialects import postgresql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from graphene import Enum, ID, Boolean, Float, Int, String, List, Field
 | 
					from graphene import Enum, ID, Boolean, Float, Int, String, List, Field, Dynamic
 | 
				
			||||||
from graphene.relay import Node
 | 
					from graphene.relay import is_node
 | 
				
			||||||
from graphene.types.json import JSONString
 | 
					from graphene.types.json import JSONString
 | 
				
			||||||
from .fields import SQLAlchemyConnectionField
 | 
					from .fields import SQLAlchemyConnectionField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -18,16 +18,20 @@ except ImportError:
 | 
				
			||||||
def convert_sqlalchemy_relationship(relationship, registry):
 | 
					def convert_sqlalchemy_relationship(relationship, registry):
 | 
				
			||||||
    direction = relationship.direction
 | 
					    direction = relationship.direction
 | 
				
			||||||
    model = relationship.mapper.entity
 | 
					    model = relationship.mapper.entity
 | 
				
			||||||
    _type = registry.get_type_for_model(model)
 | 
					
 | 
				
			||||||
    if not _type:
 | 
					    def dynamic_type():
 | 
				
			||||||
        return None
 | 
					        _type = registry.get_type_for_model(model)
 | 
				
			||||||
    if direction == interfaces.MANYTOONE:
 | 
					        if not _type:
 | 
				
			||||||
        return Field(_type)
 | 
					            return None
 | 
				
			||||||
    elif (direction == interfaces.ONETOMANY or
 | 
					        if direction == interfaces.MANYTOONE:
 | 
				
			||||||
          direction == interfaces.MANYTOMANY):
 | 
					            return Field(_type)
 | 
				
			||||||
        if issubclass(_type, Node):
 | 
					        elif (direction == interfaces.ONETOMANY or
 | 
				
			||||||
            return SQLAlchemyConnectionField(_type)
 | 
					              direction == interfaces.MANYTOMANY):
 | 
				
			||||||
        return List(_type)
 | 
					            if is_node(_type):
 | 
				
			||||||
 | 
					                return SQLAlchemyConnectionField(_type)
 | 
				
			||||||
 | 
					            return Field(List(_type))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    return Dynamic(dynamic_type)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def convert_sqlalchemy_column(column, registry=None):
 | 
					def convert_sqlalchemy_column(column, registry=None):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,3 +1,4 @@
 | 
				
			||||||
 | 
					from functools import partial
 | 
				
			||||||
from sqlalchemy.orm.query import Query
 | 
					from sqlalchemy.orm.query import Query
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from graphene.relay import ConnectionField
 | 
					from graphene.relay import ConnectionField
 | 
				
			||||||
| 
						 | 
					@ -9,17 +10,13 @@ class SQLAlchemyConnectionField(ConnectionField):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @property
 | 
					    @property
 | 
				
			||||||
    def model(self):
 | 
					    def model(self):
 | 
				
			||||||
        return self.connection._meta.node._meta.model
 | 
					        return self.type._meta.node._meta.model
 | 
				
			||||||
 | 
					 | 
				
			||||||
    def get_query(self, context):
 | 
					 | 
				
			||||||
        return get_query(self.model, context)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    def default_resolver(self, root, args, context, info):
 | 
					 | 
				
			||||||
        return getattr(root, self.source or self.attname, self.get_query(context))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def connection_resolver(resolver, connection, root, args, context, info):
 | 
					    def connection_resolver(resolver, connection, model, root, args, context, info):
 | 
				
			||||||
        iterable = resolver(root, args, context, info)
 | 
					        iterable = resolver(root, args, context, info)
 | 
				
			||||||
 | 
					        if iterable is None:
 | 
				
			||||||
 | 
					            iterable = get_query(model, context)
 | 
				
			||||||
        if isinstance(iterable, Query):
 | 
					        if isinstance(iterable, Query):
 | 
				
			||||||
            _len = iterable.count()
 | 
					            _len = iterable.count()
 | 
				
			||||||
        else:
 | 
					        else:
 | 
				
			||||||
| 
						 | 
					@ -33,3 +30,6 @@ class SQLAlchemyConnectionField(ConnectionField):
 | 
				
			||||||
            connection_type=connection,
 | 
					            connection_type=connection,
 | 
				
			||||||
            edge_type=connection.Edge,
 | 
					            edge_type=connection.Edge,
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    def get_resolver(self, parent_resolver):
 | 
				
			||||||
 | 
					        return partial(self.connection_resolver, parent_resolver, self.type, self.model)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,10 +7,10 @@ class Registry(object):
 | 
				
			||||||
        from .types import SQLAlchemyObjectType
 | 
					        from .types import SQLAlchemyObjectType
 | 
				
			||||||
        assert issubclass(cls, SQLAlchemyObjectType), 'Only SQLAlchemyObjectType can be registered, received "{}"'.format(cls.__name__)
 | 
					        assert issubclass(cls, SQLAlchemyObjectType), 'Only SQLAlchemyObjectType can be registered, received "{}"'.format(cls.__name__)
 | 
				
			||||||
        assert cls._meta.registry == self, 'Registry for a Model have to match.'
 | 
					        assert cls._meta.registry == self, 'Registry for a Model have to match.'
 | 
				
			||||||
        assert self.get_type_for_model(cls._meta.model) in [None, cls], (
 | 
					        # assert self.get_type_for_model(cls._meta.model) in [None, cls], (
 | 
				
			||||||
            'SQLAlchemy model "{}" already associated with '
 | 
					        #     'SQLAlchemy model "{}" already associated with '
 | 
				
			||||||
            'another type "{}".'
 | 
					        #     'another type "{}".'
 | 
				
			||||||
        ).format(cls._meta.model, self._registry[cls._meta.model])
 | 
					        # ).format(cls._meta.model, self._registry[cls._meta.model])
 | 
				
			||||||
        self._registry[cls._meta.model] = cls
 | 
					        self._registry[cls._meta.model] = cls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    def get_type_for_model(self, model):
 | 
					    def get_type_for_model(self, model):
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,11 +5,12 @@ from sqlalchemy_utils.types.choice import ChoiceType
 | 
				
			||||||
from sqlalchemy.dialects import postgresql
 | 
					from sqlalchemy.dialects import postgresql
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import graphene
 | 
					import graphene
 | 
				
			||||||
 | 
					from graphene.relay import Node
 | 
				
			||||||
from graphene.types.json import JSONString
 | 
					from graphene.types.json import JSONString
 | 
				
			||||||
from ..converter import (convert_sqlalchemy_column,
 | 
					from ..converter import (convert_sqlalchemy_column,
 | 
				
			||||||
                         convert_sqlalchemy_relationship)
 | 
					                         convert_sqlalchemy_relationship)
 | 
				
			||||||
from ..fields import SQLAlchemyConnectionField
 | 
					from ..fields import SQLAlchemyConnectionField
 | 
				
			||||||
from ..types import SQLAlchemyObjectType, SQLAlchemyNode
 | 
					from ..types import SQLAlchemyObjectType
 | 
				
			||||||
from ..registry import Registry
 | 
					from ..registry import Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Article, Pet, Reporter
 | 
					from .models import Article, Pet, Reporter
 | 
				
			||||||
| 
						 | 
					@ -19,7 +20,7 @@ def assert_column_conversion(sqlalchemy_type, graphene_field, **kwargs):
 | 
				
			||||||
    column = Column(sqlalchemy_type, doc='Custom Help Text', **kwargs)
 | 
					    column = Column(sqlalchemy_type, doc='Custom Help Text', **kwargs)
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_column(column)
 | 
					    graphene_type = convert_sqlalchemy_column(column)
 | 
				
			||||||
    assert isinstance(graphene_type, graphene_field)
 | 
					    assert isinstance(graphene_type, graphene_field)
 | 
				
			||||||
    field = graphene_type.as_field()
 | 
					    field = graphene_type.Field()
 | 
				
			||||||
    assert field.description == 'Custom Help Text'
 | 
					    assert field.description == 'Custom Help Text'
 | 
				
			||||||
    return field
 | 
					    return field
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -101,16 +102,17 @@ def test_should_choice_convert_enum():
 | 
				
			||||||
    Table('translatedmodel', Base.metadata, column)
 | 
					    Table('translatedmodel', Base.metadata, column)
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_column(column)
 | 
					    graphene_type = convert_sqlalchemy_column(column)
 | 
				
			||||||
    assert issubclass(graphene_type, graphene.Enum)
 | 
					    assert issubclass(graphene_type, graphene.Enum)
 | 
				
			||||||
    assert graphene_type._meta.graphql_type.name == 'TRANSLATEDMODEL_LANGUAGE'
 | 
					    assert graphene_type._meta.name == 'TRANSLATEDMODEL_LANGUAGE'
 | 
				
			||||||
    assert graphene_type._meta.graphql_type.description == 'Language'
 | 
					    assert graphene_type._meta.description == 'Language'
 | 
				
			||||||
    assert graphene_type._meta.enum.__members__['es'].value == 'Spanish'
 | 
					    assert graphene_type._meta.enum.__members__['es'].value == 'Spanish'
 | 
				
			||||||
    assert graphene_type._meta.enum.__members__['en'].value == 'English'
 | 
					    assert graphene_type._meta.enum.__members__['en'].value == 'English'
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytomany_convert_connectionorlist():
 | 
					def test_should_manytomany_convert_connectionorlist():
 | 
				
			||||||
    registry = Registry()
 | 
					    registry = Registry()
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Reporter.pets.property, registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Reporter.pets.property, registry)
 | 
				
			||||||
    assert not graphene_type
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
 | 
					    assert not dynamic_field.get_type()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytomany_convert_connectionorlist_list():
 | 
					def test_should_manytomany_convert_connectionorlist_list():
 | 
				
			||||||
| 
						 | 
					@ -118,26 +120,30 @@ def test_should_manytomany_convert_connectionorlist_list():
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Pet
 | 
					            model = Pet
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Reporter.pets.property, A._meta.registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Reporter.pets.property, A._meta.registry)
 | 
				
			||||||
    assert isinstance(graphene_type, graphene.List)
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
    assert graphene_type.of_type == A._meta.graphql_type
 | 
					    graphene_type = dynamic_field.get_type()
 | 
				
			||||||
 | 
					    assert isinstance(graphene_type, graphene.Field)
 | 
				
			||||||
 | 
					    assert isinstance(graphene_type.type, graphene.List)
 | 
				
			||||||
 | 
					    assert graphene_type.type.of_type == A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytomany_convert_connectionorlist_connection():
 | 
					def test_should_manytomany_convert_connectionorlist_connection():
 | 
				
			||||||
    class A(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					    class A(SQLAlchemyObjectType):
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Pet
 | 
					            model = Pet
 | 
				
			||||||
 | 
					            interfaces = (Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Reporter.pets.property, A._meta.registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Reporter.pets.property, A._meta.registry)
 | 
				
			||||||
    assert isinstance(graphene_type, SQLAlchemyConnectionField)
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
 | 
					    assert isinstance(dynamic_field.get_type(), SQLAlchemyConnectionField)
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytoone_convert_connectionorlist():
 | 
					def test_should_manytoone_convert_connectionorlist():
 | 
				
			||||||
    registry = Registry()
 | 
					    registry = Registry()
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Article.reporter.property, registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Article.reporter.property, registry)
 | 
				
			||||||
    assert not graphene_type
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
 | 
					    assert not dynamic_field.get_type()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytoone_convert_connectionorlist_list():
 | 
					def test_should_manytoone_convert_connectionorlist_list():
 | 
				
			||||||
| 
						 | 
					@ -145,19 +151,24 @@ def test_should_manytoone_convert_connectionorlist_list():
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Reporter
 | 
					            model = Reporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Article.reporter.property, A._meta.registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Article.reporter.property, A._meta.registry)
 | 
				
			||||||
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
 | 
					    graphene_type = dynamic_field.get_type()
 | 
				
			||||||
    assert isinstance(graphene_type, graphene.Field)
 | 
					    assert isinstance(graphene_type, graphene.Field)
 | 
				
			||||||
    assert graphene_type.type == A._meta.graphql_type
 | 
					    assert graphene_type.type == A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_manytoone_convert_connectionorlist_connection():
 | 
					def test_should_manytoone_convert_connectionorlist_connection():
 | 
				
			||||||
    class A(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					    class A(SQLAlchemyObjectType):
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Reporter
 | 
					            model = Reporter
 | 
				
			||||||
 | 
					            interfaces = (Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    graphene_type = convert_sqlalchemy_relationship(Article.reporter.property, A._meta.registry)
 | 
					    dynamic_field = convert_sqlalchemy_relationship(Article.reporter.property, A._meta.registry)
 | 
				
			||||||
 | 
					    assert isinstance(dynamic_field, graphene.Dynamic)
 | 
				
			||||||
 | 
					    graphene_type = dynamic_field.get_type()
 | 
				
			||||||
    assert isinstance(graphene_type, graphene.Field)
 | 
					    assert isinstance(graphene_type, graphene.Field)
 | 
				
			||||||
    assert graphene_type.type == A._meta.graphql_type
 | 
					    assert graphene_type.type == A
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_postgresql_uuid_convert():
 | 
					def test_should_postgresql_uuid_convert():
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,8 +3,8 @@ from sqlalchemy import create_engine
 | 
				
			||||||
from sqlalchemy.orm import scoped_session, sessionmaker
 | 
					from sqlalchemy.orm import scoped_session, sessionmaker
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import graphene
 | 
					import graphene
 | 
				
			||||||
from graphene import relay
 | 
					from graphene.relay import Node
 | 
				
			||||||
from ..types import (SQLAlchemyNode, SQLAlchemyObjectType)
 | 
					from ..types import SQLAlchemyObjectType
 | 
				
			||||||
from ..fields import SQLAlchemyConnectionField
 | 
					from ..fields import SQLAlchemyConnectionField
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from .models import Article, Base, Editor, Reporter
 | 
					from .models import Article, Base, Editor, Reporter
 | 
				
			||||||
| 
						 | 
					@ -93,10 +93,11 @@ def test_should_query_well(session):
 | 
				
			||||||
def test_should_node(session):
 | 
					def test_should_node(session):
 | 
				
			||||||
    setup_fixtures(session)
 | 
					    setup_fixtures(session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class ReporterNode(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					    class ReporterNode(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Reporter
 | 
					            model = Reporter
 | 
				
			||||||
 | 
					            interfaces = (Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        @classmethod
 | 
					        @classmethod
 | 
				
			||||||
        def get_node(cls, id, info):
 | 
					        def get_node(cls, id, info):
 | 
				
			||||||
| 
						 | 
					@ -105,17 +106,18 @@ def test_should_node(session):
 | 
				
			||||||
        def resolve_articles(self, *args, **kwargs):
 | 
					        def resolve_articles(self, *args, **kwargs):
 | 
				
			||||||
            return [Article(headline='Hi!')]
 | 
					            return [Article(headline='Hi!')]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class ArticleNode(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					    class ArticleNode(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Article
 | 
					            model = Article
 | 
				
			||||||
 | 
					            interfaces = (Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # @classmethod
 | 
					        # @classmethod
 | 
				
			||||||
        # def get_node(cls, id, info):
 | 
					        # def get_node(cls, id, info):
 | 
				
			||||||
        #     return Article(id=1, headline='Article node')
 | 
					        #     return Article(id=1, headline='Article node')
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Query(graphene.ObjectType):
 | 
					    class Query(graphene.ObjectType):
 | 
				
			||||||
        node = SQLAlchemyNode.Field()
 | 
					        node = Node.Field()
 | 
				
			||||||
        reporter = graphene.Field(ReporterNode)
 | 
					        reporter = graphene.Field(ReporterNode)
 | 
				
			||||||
        article = graphene.Field(ArticleNode)
 | 
					        article = graphene.Field(ArticleNode)
 | 
				
			||||||
        all_articles = SQLAlchemyConnectionField(ArticleNode)
 | 
					        all_articles = SQLAlchemyConnectionField(ArticleNode)
 | 
				
			||||||
| 
						 | 
					@ -194,13 +196,14 @@ def test_should_node(session):
 | 
				
			||||||
def test_should_custom_identifier(session):
 | 
					def test_should_custom_identifier(session):
 | 
				
			||||||
    setup_fixtures(session)
 | 
					    setup_fixtures(session)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class EditorNode(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					    class EditorNode(SQLAlchemyObjectType):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Editor
 | 
					            model = Editor
 | 
				
			||||||
 | 
					            interfaces = (Node, )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Query(graphene.ObjectType):
 | 
					    class Query(graphene.ObjectType):
 | 
				
			||||||
        node = SQLAlchemyNode.Field()
 | 
					        node = Node.Field()
 | 
				
			||||||
        all_editors = SQLAlchemyConnectionField(EditorNode)
 | 
					        all_editors = SQLAlchemyConnectionField(EditorNode)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    query = '''
 | 
					    query = '''
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,7 +28,7 @@ def test_should_map_fields_correctly():
 | 
				
			||||||
            model = Reporter
 | 
					            model = Reporter
 | 
				
			||||||
            registry = Registry()
 | 
					            registry = Registry()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    assert ReporterType2._meta.get_fields().keys() == ['id', 'firstName', 'lastName', 'email']
 | 
					    assert ReporterType2._meta.fields.keys() == ['id', 'first_name', 'last_name', 'email', 'pets', 'articles']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_should_map_only_few_fields():
 | 
					def test_should_map_only_few_fields():
 | 
				
			||||||
| 
						 | 
					@ -36,5 +36,5 @@ def test_should_map_only_few_fields():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        class Meta:
 | 
					        class Meta:
 | 
				
			||||||
            model = Reporter
 | 
					            model = Reporter
 | 
				
			||||||
            only = ('id', 'email')
 | 
					            only_fields = ('id', 'email')
 | 
				
			||||||
    assert Reporter2._meta.get_fields().keys() == ['id', 'email']
 | 
					    assert Reporter2._meta.fields.keys() == ['id', 'email']
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,10 +1,10 @@
 | 
				
			||||||
from graphql.type import GraphQLObjectType, GraphQLInterfaceType
 | 
					from graphql.type import GraphQLObjectType, GraphQLInterfaceType
 | 
				
			||||||
from graphql.type.definition import GraphQLFieldDefinition
 | 
					 | 
				
			||||||
from graphql import GraphQLInt
 | 
					from graphql import GraphQLInt
 | 
				
			||||||
from pytest import raises
 | 
					from pytest import raises
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from graphene import Schema
 | 
					from graphene import Schema, Interface, ObjectType
 | 
				
			||||||
from ..types import (SQLAlchemyNode, SQLAlchemyObjectType)
 | 
					from graphene.relay import Node, is_node
 | 
				
			||||||
 | 
					from ..types import SQLAlchemyObjectType
 | 
				
			||||||
from ..registry import Registry
 | 
					from ..registry import Registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from graphene import Field, Int
 | 
					from graphene import Field, Int
 | 
				
			||||||
| 
						 | 
					@ -14,6 +14,7 @@ from .models import Article, Reporter
 | 
				
			||||||
 | 
					
 | 
				
			||||||
registry = Registry()
 | 
					registry = Registry()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Character(SQLAlchemyObjectType):
 | 
					class Character(SQLAlchemyObjectType):
 | 
				
			||||||
    '''Character description'''
 | 
					    '''Character description'''
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
| 
						 | 
					@ -21,22 +22,21 @@ class Character(SQLAlchemyObjectType):
 | 
				
			||||||
        registry = registry
 | 
					        registry = registry
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class Human(SQLAlchemyNode, SQLAlchemyObjectType):
 | 
					class Human(SQLAlchemyObjectType):
 | 
				
			||||||
    '''Human description'''
 | 
					    '''Human description'''
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    pub_date = Int()
 | 
					    pub_date = Int()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    class Meta:
 | 
					    class Meta:
 | 
				
			||||||
        model = Article
 | 
					        model = Article
 | 
				
			||||||
        exclude = ('id', )
 | 
					        exclude_fields = ('id', )
 | 
				
			||||||
        registry = registry
 | 
					        registry = registry
 | 
				
			||||||
 | 
					        interfaces = (Node, )
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_sqlalchemy_interface():
 | 
					def test_sqlalchemy_interface():
 | 
				
			||||||
    assert isinstance(SQLAlchemyNode._meta.graphql_type, GraphQLInterfaceType)
 | 
					    assert issubclass(Node, Interface)
 | 
				
			||||||
 | 
					    assert issubclass(Node, Node)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# @patch('graphene.contrib.sqlalchemy.tests.models.Article.filter', return_value=Article(id=1))
 | 
					# @patch('graphene.contrib.sqlalchemy.tests.models.Article.filter', return_value=Article(id=1))
 | 
				
			||||||
| 
						 | 
					@ -47,14 +47,13 @@ def test_sqlalchemy_interface():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_objecttype_registered():
 | 
					def test_objecttype_registered():
 | 
				
			||||||
    object_type = Character._meta.graphql_type
 | 
					    assert issubclass(Character, ObjectType)
 | 
				
			||||||
    assert isinstance(object_type, GraphQLObjectType)
 | 
					 | 
				
			||||||
    assert Character._meta.model == Reporter
 | 
					    assert Character._meta.model == Reporter
 | 
				
			||||||
    assert object_type.get_fields().keys() == ['articles', 'id', 'firstName', 'lastName', 'email']
 | 
					    assert Character._meta.fields.keys() == ['id', 'first_name', 'last_name', 'email', 'pets', 'articles']
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
# def test_sqlalchemynode_idfield():
 | 
					# def test_sqlalchemynode_idfield():
 | 
				
			||||||
#     idfield = SQLAlchemyNode._meta.fields_map['id']
 | 
					#     idfield = Node._meta.fields_map['id']
 | 
				
			||||||
#     assert isinstance(idfield, GlobalIDField)
 | 
					#     assert isinstance(idfield, GlobalIDField)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -64,14 +63,12 @@ def test_objecttype_registered():
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_node_replacedfield():
 | 
					def test_node_replacedfield():
 | 
				
			||||||
    idfield = Human._meta.graphql_type.get_fields()['pubDate']
 | 
					    idfield = Human._meta.fields['pub_date']
 | 
				
			||||||
    assert isinstance(idfield, GraphQLFieldDefinition)
 | 
					    assert isinstance(idfield, Field)
 | 
				
			||||||
    assert idfield.type == GraphQLInt
 | 
					    assert idfield.type == Int
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
def test_object_type():
 | 
					def test_object_type():
 | 
				
			||||||
    object_type = Human._meta.graphql_type
 | 
					    assert issubclass(Human, ObjectType)
 | 
				
			||||||
    object_type.get_fields()
 | 
					    assert Human._meta.fields.keys() == ['id', 'pub_date', 'headline', 'reporter_id', 'reporter']
 | 
				
			||||||
    assert isinstance(object_type, GraphQLObjectType)
 | 
					    assert is_node(Human)
 | 
				
			||||||
    assert object_type.get_fields().keys() == ['id', 'pubDate', 'reporter', 'headline', 'reporterId']
 | 
					 | 
				
			||||||
    assert SQLAlchemyNode._meta.graphql_type in object_type.get_interfaces()
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,138 +1,112 @@
 | 
				
			||||||
 | 
					from collections import OrderedDict
 | 
				
			||||||
import six
 | 
					import six
 | 
				
			||||||
from sqlalchemy.inspection import inspect as sqlalchemyinspect
 | 
					from sqlalchemy.inspection import inspect as sqlalchemyinspect
 | 
				
			||||||
from sqlalchemy.orm.exc import NoResultFound
 | 
					from sqlalchemy.orm.exc import NoResultFound
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from graphene import ObjectType
 | 
					from graphene import ObjectType
 | 
				
			||||||
from graphene.relay import Node
 | 
					from graphene.relay import is_node
 | 
				
			||||||
from .converter import (convert_sqlalchemy_column,
 | 
					from .converter import (convert_sqlalchemy_column,
 | 
				
			||||||
                        convert_sqlalchemy_relationship)
 | 
					                        convert_sqlalchemy_relationship)
 | 
				
			||||||
from .utils import is_mapped
 | 
					from .utils import is_mapped
 | 
				
			||||||
 | 
					
 | 
				
			||||||
from functools import partial
 | 
					from graphene.types.objecttype import ObjectTypeMeta
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from graphene import Field, Interface
 | 
					 | 
				
			||||||
from graphene.types.options import Options
 | 
					from graphene.types.options import Options
 | 
				
			||||||
from graphene.types.objecttype import attrs_without_fields, get_interfaces
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
from .registry import Registry, get_global_registry
 | 
					from .registry import Registry, get_global_registry
 | 
				
			||||||
from .utils import get_query
 | 
					 | 
				
			||||||
from graphene.utils.is_base_type import is_base_type
 | 
					from graphene.utils.is_base_type import is_base_type
 | 
				
			||||||
from graphene.utils.copy_fields import copy_fields
 | 
					from graphene.types.utils import get_fields_in_type
 | 
				
			||||||
from graphene.utils.get_graphql_type import get_graphql_type
 | 
					from .utils import get_query
 | 
				
			||||||
from graphene.utils.get_fields import get_fields
 | 
					 | 
				
			||||||
from graphene.utils.as_field import as_field
 | 
					 | 
				
			||||||
from graphene.generators import generate_objecttype
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SQLAlchemyObjectTypeMeta(type(ObjectType)):
 | 
					class SQLAlchemyObjectTypeMeta(ObjectTypeMeta):
 | 
				
			||||||
    def _construct_fields(cls, fields, options):
 | 
					    def _construct_fields(cls, all_fields, options):
 | 
				
			||||||
        only_fields = cls._meta.only
 | 
					        only_fields = cls._meta.only_fields
 | 
				
			||||||
        exclude_fields = cls._meta.exclude
 | 
					        exclude_fields = cls._meta.exclude_fields
 | 
				
			||||||
        inspected_model = sqlalchemyinspect(cls._meta.model)
 | 
					        inspected_model = sqlalchemyinspect(cls._meta.model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        # Get all the columns for the relationships on the model
 | 
					        fields = OrderedDict()
 | 
				
			||||||
        for relationship in inspected_model.relationships:
 | 
					 | 
				
			||||||
            is_not_in_only = only_fields and relationship.key not in only_fields
 | 
					 | 
				
			||||||
            is_already_created = relationship.key in fields
 | 
					 | 
				
			||||||
            is_excluded = relationship.key in exclude_fields or is_already_created
 | 
					 | 
				
			||||||
            if is_not_in_only or is_excluded:
 | 
					 | 
				
			||||||
                # We skip this field if we specify only_fields and is not
 | 
					 | 
				
			||||||
                # in there. Or when we excldue this field in exclude_fields
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            converted_relationship = convert_sqlalchemy_relationship(relationship, options.registry)
 | 
					 | 
				
			||||||
            if not converted_relationship:
 | 
					 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            name = relationship.key
 | 
					 | 
				
			||||||
            fields[name] = as_field(converted_relationship)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        for name, column in inspected_model.columns.items():
 | 
					        for name, column in inspected_model.columns.items():
 | 
				
			||||||
            is_not_in_only = only_fields and name not in only_fields
 | 
					            is_not_in_only = only_fields and name not in only_fields
 | 
				
			||||||
            is_already_created = name in fields
 | 
					            is_already_created = name in all_fields
 | 
				
			||||||
            is_excluded = name in exclude_fields or is_already_created
 | 
					            is_excluded = name in exclude_fields or is_already_created
 | 
				
			||||||
            if is_not_in_only or is_excluded:
 | 
					            if is_not_in_only or is_excluded:
 | 
				
			||||||
                # We skip this field if we specify only_fields and is not
 | 
					                # We skip this field if we specify only_fields and is not
 | 
				
			||||||
                # in there. Or when we excldue this field in exclude_fields
 | 
					                # in there. Or when we excldue this field in exclude_fields
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            converted_column = convert_sqlalchemy_column(column, options.registry)
 | 
					            converted_column = convert_sqlalchemy_column(column, options.registry)
 | 
				
			||||||
            if not converted_column:
 | 
					            fields[name] = converted_column
 | 
				
			||||||
                continue
 | 
					 | 
				
			||||||
            fields[name] = as_field(converted_column)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        fields = copy_fields(Field, fields, parent=cls)
 | 
					        # Get all the columns for the relationships on the model
 | 
				
			||||||
 | 
					        for relationship in inspected_model.relationships:
 | 
				
			||||||
 | 
					            is_not_in_only = only_fields and relationship.key not in only_fields
 | 
				
			||||||
 | 
					            is_already_created = relationship.key in all_fields
 | 
				
			||||||
 | 
					            is_excluded = relationship.key in exclude_fields or is_already_created
 | 
				
			||||||
 | 
					            if is_not_in_only or is_excluded:
 | 
				
			||||||
 | 
					                # We skip this field if we specify only_fields and is not
 | 
				
			||||||
 | 
					                # in there. Or when we excldue this field in exclude_fields
 | 
				
			||||||
 | 
					                continue
 | 
				
			||||||
 | 
					            converted_relationship = convert_sqlalchemy_relationship(relationship, options.registry)
 | 
				
			||||||
 | 
					            name = relationship.key
 | 
				
			||||||
 | 
					            fields[name] = converted_relationship
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return fields
 | 
					        return fields
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @staticmethod
 | 
					    @staticmethod
 | 
				
			||||||
    def _create_objecttype(cls, name, bases, attrs):
 | 
					    def __new__(cls, name, bases, attrs):
 | 
				
			||||||
        # super_new = super(SQLAlchemyObjectTypeMeta, cls).__new__
 | 
					 | 
				
			||||||
        super_new = type.__new__
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        # Also ensure initialization is only performed for subclasses of Model
 | 
					        # Also ensure initialization is only performed for subclasses of Model
 | 
				
			||||||
        # (excluding Model class itself).
 | 
					        # (excluding Model class itself).
 | 
				
			||||||
        if not is_base_type(bases, SQLAlchemyObjectTypeMeta):
 | 
					        if not is_base_type(bases, SQLAlchemyObjectTypeMeta):
 | 
				
			||||||
            return super_new(cls, name, bases, attrs)
 | 
					            return type.__new__(cls, name, bases, attrs)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options = Options(
 | 
					        options = Options(
 | 
				
			||||||
            attrs.pop('Meta', None),
 | 
					            attrs.pop('Meta', None),
 | 
				
			||||||
            name=None,
 | 
					            name=name,
 | 
				
			||||||
            description=None,
 | 
					            description=attrs.pop('__doc__', None),
 | 
				
			||||||
            model=None,
 | 
					            model=None,
 | 
				
			||||||
            fields=(),
 | 
					            fields=None,
 | 
				
			||||||
            exclude=(),
 | 
					            only_fields=(),
 | 
				
			||||||
            only=(),
 | 
					            exclude_fields=(),
 | 
				
			||||||
 | 
					            id='id',
 | 
				
			||||||
            interfaces=(),
 | 
					            interfaces=(),
 | 
				
			||||||
            registry=None
 | 
					            registry=None
 | 
				
			||||||
        )
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if not options.registry:
 | 
					        if not options.registry:
 | 
				
			||||||
            options.registry = get_global_registry()
 | 
					            options.registry = get_global_registry()
 | 
				
			||||||
        assert isinstance(options.registry, Registry), 'The attribute registry in {}.Meta needs to be an instance of Registry, received "{}".'.format(name, options.registry)
 | 
					        assert isinstance(options.registry, Registry), (
 | 
				
			||||||
        assert is_mapped(options.model), 'You need to pass a valid SQLAlchemy Model in {}.Meta, received "{}".'.format(name, options.model)
 | 
					            'The attribute registry in {}.Meta needs to be an'
 | 
				
			||||||
 | 
					            ' instance of Registry, received "{}".'
 | 
				
			||||||
 | 
					        ).format(name, options.registry)
 | 
				
			||||||
 | 
					        assert is_mapped(options.model), (
 | 
				
			||||||
 | 
					            'You need to pass a valid SQLAlchemy Model in '
 | 
				
			||||||
 | 
					            '{}.Meta, received "{}".'
 | 
				
			||||||
 | 
					        ).format(name, options.model)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        interfaces = tuple(options.interfaces)
 | 
					 | 
				
			||||||
        fields = get_fields(ObjectType, attrs, bases, interfaces)
 | 
					 | 
				
			||||||
        attrs = attrs_without_fields(attrs, fields)
 | 
					 | 
				
			||||||
        cls = super_new(cls, name, bases, dict(attrs, _meta=options))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        base_interfaces = tuple(b for b in bases if issubclass(b, Interface))
 | 
					        cls = ObjectTypeMeta.__new__(cls, name, bases, dict(attrs, _meta=options))
 | 
				
			||||||
        options.get_fields = partial(cls._construct_fields, fields, options)
 | 
					 | 
				
			||||||
        options.get_interfaces = tuple(get_interfaces(interfaces + base_interfaces))
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
        options.graphql_type = generate_objecttype(cls)
 | 
					        options.registry.register(cls)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        if issubclass(cls, SQLAlchemyObjectType):
 | 
					        options.sqlalchemy_fields = get_fields_in_type(
 | 
				
			||||||
            options.registry.register(cls)
 | 
					            ObjectType,
 | 
				
			||||||
 | 
					            cls._construct_fields(options.fields, options)
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					        options.fields.update(options.sqlalchemy_fields)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        return cls
 | 
					        return cls
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
class SQLAlchemyObjectType(six.with_metaclass(SQLAlchemyObjectTypeMeta, ObjectType)):
 | 
					class SQLAlchemyObjectType(six.with_metaclass(SQLAlchemyObjectTypeMeta, ObjectType)):
 | 
				
			||||||
    is_type_of = None
 | 
					    @classmethod
 | 
				
			||||||
 | 
					    def is_type_of(cls, root, context, info):
 | 
				
			||||||
 | 
					        if isinstance(root, cls):
 | 
				
			||||||
 | 
					            return True
 | 
				
			||||||
 | 
					        if not is_mapped(type(root)):
 | 
				
			||||||
 | 
					            raise Exception((
 | 
				
			||||||
 | 
					                'Received incompatible instance "{}".'
 | 
				
			||||||
 | 
					            ).format(root))
 | 
				
			||||||
 | 
					        return type(root) == cls._meta.model
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
class SQLAlchemyNodeMeta(SQLAlchemyObjectTypeMeta, type(Node)):
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def _get_interface_options(meta):
 | 
					 | 
				
			||||||
        return Options(
 | 
					 | 
				
			||||||
            meta,
 | 
					 | 
				
			||||||
            name=None,
 | 
					 | 
				
			||||||
            description=None,
 | 
					 | 
				
			||||||
            graphql_type=None,
 | 
					 | 
				
			||||||
            registry=False
 | 
					 | 
				
			||||||
        )
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
    @staticmethod
 | 
					 | 
				
			||||||
    def _create_interface(cls, name, bases, attrs):
 | 
					 | 
				
			||||||
        cls = super(SQLAlchemyNodeMeta, cls)._create_interface(cls, name, bases, attrs)
 | 
					 | 
				
			||||||
        if not cls._meta.registry:
 | 
					 | 
				
			||||||
            cls._meta.registry = get_global_registry()
 | 
					 | 
				
			||||||
        assert isinstance(cls._meta.registry, Registry), 'The attribute registry in {}.Meta needs to be an instance of Registry.'.format(name)
 | 
					 | 
				
			||||||
        return cls
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
class SQLAlchemyNode(six.with_metaclass(SQLAlchemyNodeMeta, Node)):
 | 
					 | 
				
			||||||
    @classmethod
 | 
					    @classmethod
 | 
				
			||||||
    def get_node(cls, id, context, info):
 | 
					    def get_node(cls, id, context, info):
 | 
				
			||||||
        try:
 | 
					        try:
 | 
				
			||||||
| 
						 | 
					@ -142,16 +116,8 @@ class SQLAlchemyNode(six.with_metaclass(SQLAlchemyNodeMeta, Node)):
 | 
				
			||||||
        except NoResultFound:
 | 
					        except NoResultFound:
 | 
				
			||||||
            return None
 | 
					            return None
 | 
				
			||||||
 | 
					
 | 
				
			||||||
    @classmethod
 | 
					    def resolve_id(root, args, context, info):
 | 
				
			||||||
    def resolve_id(cls, root, args, context, info):
 | 
					        graphene_type = info.parent_type.graphene_type
 | 
				
			||||||
        return root.__mapper__.primary_key_from_instance(root)[0]
 | 
					        if is_node(graphene_type):
 | 
				
			||||||
 | 
					            return root.__mapper__.primary_key_from_instance(root)[0]
 | 
				
			||||||
    @classmethod
 | 
					        return getattr(root, graphene_type._meta.id, None)
 | 
				
			||||||
    def resolve_type(cls, type_instance, context, info):
 | 
					 | 
				
			||||||
        # We get the model from the _meta in the SQLAlchemy class/instance
 | 
					 | 
				
			||||||
        model = type(type_instance)
 | 
					 | 
				
			||||||
        graphene_type = cls._meta.registry.get_type_for_model(model)
 | 
					 | 
				
			||||||
        if graphene_type:
 | 
					 | 
				
			||||||
            return get_graphql_type(graphene_type)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
        raise Exception("Type not found for model \"{}\"".format(model))
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
		Reference in New Issue
	
	Block a user