refactor: make relay connections extendable

This commit is contained in:
Erik Wrede 2023-03-02 22:36:07 +01:00
parent 8596349405
commit 828e951c0e
2 changed files with 72 additions and 15 deletions

View File

@ -61,8 +61,9 @@ class Connection(ObjectType):
abstract = True
@classmethod
def __init_subclass_with_meta__(cls, node=None, name=None, **options):
_meta = ConnectionOptions(cls)
def __init_subclass_with_meta__(cls, node=None, name=None, _meta=None, **options):
if not _meta:
_meta = ConnectionOptions(cls)
assert node, f"You have to provide a node in {cls.__name__}.Meta"
assert isinstance(node, NonNull) or issubclass(
node, (Scalar, Enum, ObjectType, Interface, Union, NonNull)
@ -92,19 +93,26 @@ class Connection(ObjectType):
cls.Edge = edge
options["name"] = name
_meta.node = node
_meta.fields = {
"page_info": Field(
PageInfo,
name="pageInfo",
required=True,
description="Pagination data for this connection.",
),
"edges": Field(
NonNull(List(edge)),
description="Contains the nodes in this connection.",
),
}
if not _meta.fields:
_meta.fields = {}
_meta.fields.update(
{
"page_info": Field(
PageInfo,
name="pageInfo",
required=True,
description="Pagination data for this connection.",
),
"edges": Field(
NonNull(List(edge)),
description="Contains the nodes in this connection.",
),
}
)
return super(Connection, cls).__init_subclass_with_meta__(
_meta=_meta, **options
)

View File

@ -1,7 +1,7 @@
from pytest import raises
from ...types import Argument, Field, Int, List, NonNull, ObjectType, Schema, String
from ..connection import Connection, ConnectionField, PageInfo
from ..connection import Connection, ConnectionField, PageInfo, ConnectionOptions
from ..node import Node
@ -51,6 +51,55 @@ def test_connection_inherit_abstracttype():
assert list(fields) == ["page_info", "edges", "extra"]
def test_connection_extra_abstract_fields():
class ConnectionWithNodes(Connection):
class Meta:
abstract = True
@classmethod
def __init_subclass_with_meta__(cls, node=None, name=None, **options):
_meta = ConnectionOptions(cls)
_meta.fields = {
"nodes": Field(
NonNull(List(node)),
description="Contains all the nodes in this connection.",
),
}
return super(ConnectionWithNodes, cls).__init_subclass_with_meta__(
node=node, name=name, _meta=_meta, **options
)
class MyObjectConnection(ConnectionWithNodes):
class Meta:
node = MyObject
class Edge:
other = String()
assert MyObjectConnection._meta.name == "MyObjectConnection"
fields = MyObjectConnection._meta.fields
assert list(fields) == ["nodes", "page_info", "edges"]
edge_field = fields["edges"]
pageinfo_field = fields["page_info"]
nodes_field = fields["nodes"]
assert isinstance(edge_field, Field)
assert isinstance(edge_field.type, NonNull)
assert isinstance(edge_field.type.of_type, List)
assert edge_field.type.of_type.of_type == MyObjectConnection.Edge
assert isinstance(pageinfo_field, Field)
assert isinstance(pageinfo_field.type, NonNull)
assert pageinfo_field.type.of_type == PageInfo
assert isinstance(nodes_field, Field)
assert isinstance(nodes_field.type, NonNull)
assert isinstance(nodes_field.type.of_type, List)
assert nodes_field.type.of_type.of_type == MyObject
def test_connection_name():
custom_name = "MyObjectCustomNameConnection"