mirror of
				https://github.com/graphql-python/graphene.git
				synced 2025-10-31 16:07:27 +03:00 
			
		
		
		
	First stage separate interfaces
This commit is contained in:
		
							parent
							
								
									ff3968faea
								
							
						
					
					
						commit
						04492600e5
					
				|  | @ -4,7 +4,9 @@ from graphene import relay, resolve_only_args | ||||||
| from .data import create_ship, get_empire, get_faction, get_rebels, get_ship | from .data import create_ship, get_empire, get_faction, get_rebels, get_ship | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Ship(relay.Node, graphene.ObjectType): | class Ship(graphene.ObjectType): | ||||||
|  |     class Meta: | ||||||
|  |         interfaces = [relay.Node] | ||||||
|     '''A ship in the Star Wars saga''' |     '''A ship in the Star Wars saga''' | ||||||
|     name = graphene.String(description='The name of the ship.') |     name = graphene.String(description='The name of the ship.') | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -96,8 +96,8 @@ class IterableConnectionField(Field): | ||||||
|     @property |     @property | ||||||
|     def connection(self): |     def connection(self): | ||||||
|         from .node import Node |         from .node import Node | ||||||
|         if issubclass(self._type, Node): |         if Node in self._type._meta.interfaces: | ||||||
|             connection_type = self._type.get_default_connection() |             connection_type = self._type.Connection | ||||||
|         else: |         else: | ||||||
|             connection_type = self._type |             connection_type = self._type | ||||||
|         assert issubclass(connection_type, Connection), '{} type have to be a subclass of Connection'.format(str(self)) |         assert issubclass(connection_type, Connection), '{} type have to be a subclass of Connection'.format(str(self)) | ||||||
|  |  | ||||||
|  | @ -12,6 +12,15 @@ from ..utils.copy_fields import copy_fields | ||||||
| from .connection import Connection | from .connection import Connection | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|  | def get_default_connection(cls): | ||||||
|  |     assert issubclass(cls, ObjectType), 'Can only get connection type on implemented Nodes.' | ||||||
|  | 
 | ||||||
|  |     class Meta: | ||||||
|  |         node = cls | ||||||
|  | 
 | ||||||
|  |     return type('{}Connection'.format(cls.__name__), (Connection,), {'Meta': Meta}) | ||||||
|  | 
 | ||||||
|  | 
 | ||||||
| # We inherit from ObjectTypeMeta as we want to allow | # We inherit from ObjectTypeMeta as we want to allow | ||||||
| # inheriting from Node, and also ObjectType. | # inheriting from Node, and also ObjectType. | ||||||
| # Like class MyNode(Node): pass | # Like class MyNode(Node): pass | ||||||
|  | @ -24,17 +33,6 @@ class NodeMeta(ObjectTypeMeta): | ||||||
|             meta, |             meta, | ||||||
|         ) |         ) | ||||||
| 
 | 
 | ||||||
|     @staticmethod |  | ||||||
|     def _create_objecttype(cls, name, bases, attrs): |  | ||||||
|         cls = super(NodeMeta, cls)._create_objecttype(cls, name, bases, attrs) |  | ||||||
|         require_get_node = Node._meta.graphql_type in cls._meta.graphql_type._provided_interfaces |  | ||||||
|         if require_get_node: |  | ||||||
|             assert hasattr( |  | ||||||
|                 cls, 'get_node'), '{}.get_node method is required by the Node interface.'.format( |  | ||||||
|                 cls.__name__) |  | ||||||
| 
 |  | ||||||
|         return cls |  | ||||||
| 
 |  | ||||||
|     @staticmethod |     @staticmethod | ||||||
|     def _create_interface(cls, name, bases, attrs): |     def _create_interface(cls, name, bases, attrs): | ||||||
|         options = cls._get_interface_options(attrs.pop('Meta', None)) |         options = cls._get_interface_options(attrs.pop('Meta', None)) | ||||||
|  | @ -95,10 +93,14 @@ class Node(six.with_metaclass(NodeMeta, Interface)): | ||||||
|         return graphql_type.graphene_type.get_node(_id, context, info) |         return graphql_type.graphene_type.get_node(_id, context, info) | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|     def get_default_connection(cls): |     def implements(cls, objecttype): | ||||||
|         assert issubclass(cls, ObjectType), 'Can only get connection type on implemented Nodes.' |         require_get_node = Node._meta.graphql_type in objecttype._meta.get_interfaces | ||||||
|         if not cls._connection: |         get_connection = getattr(objecttype, 'get_connection', None) | ||||||
|             class Meta: |         if not get_connection: | ||||||
|                 node = cls |             get_connection = partial(get_default_connection, objecttype) | ||||||
|             cls._connection = type('{}Connection'.format(cls.__name__), (Connection,), {'Meta': Meta}) | 
 | ||||||
|         return cls._connection |         objecttype.Connection = get_connection() | ||||||
|  |         if require_get_node: | ||||||
|  |             assert hasattr( | ||||||
|  |                 objecttype, 'get_node'), '{}.get_node method is required by the Node interface.'.format( | ||||||
|  |                 objecttype.__name__) | ||||||
|  |  | ||||||
|  | @ -6,7 +6,9 @@ from ..connection import Connection | ||||||
| from ..node import Node | from ..node import Node | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MyObject(Node, ObjectType): | class MyObject(ObjectType): | ||||||
|  |     class Meta: | ||||||
|  |         interfaces = [Node] | ||||||
|     field = String() |     field = String() | ||||||
| 
 | 
 | ||||||
|     @classmethod |     @classmethod | ||||||
|  |  | ||||||
|  | @ -8,8 +8,9 @@ from ..connection import Connection | ||||||
| from ..node import Node | from ..node import Node | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class MyNode(Node, ObjectType): | class MyNode(ObjectType): | ||||||
| 
 |     class Meta: | ||||||
|  |         interfaces = [Node] | ||||||
|     name = String() |     name = String() | ||||||
| 
 | 
 | ||||||
|     @staticmethod |     @staticmethod | ||||||
|  | @ -46,12 +47,12 @@ def test_node_good(): | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_node_get_connection(): | def test_node_get_connection(): | ||||||
|     connection = MyNode.get_default_connection() |     connection = MyNode.Connection | ||||||
|     assert issubclass(connection, Connection) |     assert issubclass(connection, Connection) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_node_get_connection_dont_duplicate(): | def test_node_get_connection_dont_duplicate(): | ||||||
|     assert MyNode.get_default_connection() == MyNode.get_default_connection() |     assert MyNode.Connection == MyNode.Connection | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_node_query(): | def test_node_query(): | ||||||
|  |  | ||||||
|  | @ -24,12 +24,15 @@ class BasePhoto(Interface): | ||||||
|     width = Int() |     width = Int() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class User(CustomNode, ObjectType): | class User(ObjectType): | ||||||
|  |     class Meta: | ||||||
|  |         interfaces = [CustomNode] | ||||||
|     name = String() |     name = String() | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| class Photo(CustomNode, BasePhoto, ObjectType): | class Photo(ObjectType): | ||||||
|     pass |     class Meta: | ||||||
|  |         interfaces = [CustomNode, BasePhoto] | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| user_data = { | user_data = { | ||||||
|  | @ -50,7 +53,6 @@ schema = Schema(query=RootQuery, types=[User, Photo]) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
| def test_str_schema_correct(): | def test_str_schema_correct(): | ||||||
|     print str(schema) |  | ||||||
|     assert str(schema) == '''schema { |     assert str(schema) == '''schema { | ||||||
|   query: RootQuery |   query: RootQuery | ||||||
| } | } | ||||||
|  |  | ||||||
|  | @ -1,4 +1,4 @@ | ||||||
| 
 | import inspect | ||||||
| import six | import six | ||||||
| 
 | 
 | ||||||
| from ..utils.copy_fields import copy_fields | from ..utils.copy_fields import copy_fields | ||||||
|  | @ -97,12 +97,17 @@ class ObjectTypeMeta(type): | ||||||
| 
 | 
 | ||||||
|         if not options.graphql_type: |         if not options.graphql_type: | ||||||
|             fields = copy_fields(Field, fields, parent=cls) |             fields = copy_fields(Field, fields, parent=cls) | ||||||
|             base_interfaces = tuple(b for b in bases if issubclass(b, Interface)) |             inherited_interfaces = tuple(b for b in bases if issubclass(b, Interface)) | ||||||
|             options.get_fields = lambda: fields |             options.get_fields = lambda: fields | ||||||
|             options.get_interfaces = tuple(get_interfaces(interfaces + base_interfaces)) |             options.interfaces = interfaces + inherited_interfaces | ||||||
|  |             options.get_interfaces = tuple(get_interfaces(options.interfaces)) | ||||||
|             options.graphql_type = generate_objecttype(cls) |             options.graphql_type = generate_objecttype(cls) | ||||||
|  |             for i in options.interfaces: | ||||||
|  |                 if inspect.isclass(i) and issubclass(i, Interface): | ||||||
|  |                     i.implements(cls) | ||||||
|         else: |         else: | ||||||
|             assert not fields, "Can't mount Fields in an ObjectType with a defined graphql_type" |             assert not fields, "Can't mount Fields in an ObjectType with a defined graphql_type" | ||||||
|  |             assert not interfaces, "Can't have extra interfaces with a defined graphql_type" | ||||||
|             fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) |             fields = copy_fields(Field, options.graphql_type.get_fields(), parent=cls) | ||||||
| 
 | 
 | ||||||
|             options.get_fields = lambda: fields |             options.get_fields = lambda: fields | ||||||
|  | @ -175,3 +180,7 @@ class Interface(six.with_metaclass(ObjectTypeMeta)): | ||||||
|         if not isinstance(self, ObjectType): |         if not isinstance(self, ObjectType): | ||||||
|             raise Exception("An interface cannot be intitialized") |             raise Exception("An interface cannot be intitialized") | ||||||
|         super(Interface, self).__init__(*args, **kwargs) |         super(Interface, self).__init__(*args, **kwargs) | ||||||
|  | 
 | ||||||
|  |     @classmethod | ||||||
|  |     def implements(cls, objecttype): | ||||||
|  |         pass | ||||||
|  |  | ||||||
		Loading…
	
		Reference in New Issue
	
	Block a user