Skip to content

Commit fabf714

Browse files
author
Mark Edwards
committed
Define protocols for connection type overrides
1 parent 4c29756 commit fabf714

File tree

4 files changed

+75
-17
lines changed

4 files changed

+75
-17
lines changed

Diff for: pyproject.toml

+1
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,7 @@ packages = [
3131
[tool.poetry.dependencies]
3232
python = "^3.6"
3333
graphql-core = "^3.0"
34+
typing-extensions = { version = "^3.6.2", python = "<3.8" }
3435

3536
[tool.poetry.dev-dependencies]
3637
pytest = "^5.3"

Diff for: setup.py

+4-1
Original file line numberDiff line numberDiff line change
@@ -29,7 +29,10 @@
2929
"Programming Language :: Python :: 3.8",
3030
"Programming Language :: Python :: Implementation :: PyPy",
3131
],
32-
install_requires=["graphql-core>=3.0.0"],
32+
install_requires=[
33+
"graphql-core>=3.0.0",
34+
"typing-extensions>=3.6.2,<4; python_version < '3.8'",
35+
],
3336
python_requires=">=3.6,<4",
3437
packages=find_packages("src"),
3538
package_dir={"": "src"},

Diff for: src/graphql_relay/connection/arrayconnection.py

+20-16
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,13 @@
66
from .connectiontypes import (
77
Connection,
88
ConnectionArguments,
9+
ConnectionConstructor,
910
ConnectionCursor,
11+
ConnectionType,
1012
Edge,
13+
EdgeConstructor,
1114
PageInfo,
15+
PageInfoConstructor,
1216
)
1317

1418
__all__ = [
@@ -24,10 +28,10 @@
2428
def connection_from_array(
2529
data: Sequence,
2630
args: ConnectionArguments = None,
27-
connection_type: Any = Connection,
28-
edge_type: Any = Edge,
29-
page_info_type: Any = PageInfo,
30-
) -> Connection:
31+
connection_type: ConnectionConstructor = Connection,
32+
edge_type: EdgeConstructor = Edge,
33+
page_info_type: PageInfoConstructor = PageInfo,
34+
) -> ConnectionType:
3135
"""Create a connection object from a sequence of objects.
3236
3337
Note that different from its JavaScript counterpart which expects an array,
@@ -54,10 +58,10 @@ def connection_from_array(
5458
def connection_from_list(
5559
data: Sequence,
5660
args: ConnectionArguments = None,
57-
connection_type: Any = Connection,
58-
edge_type: Any = Edge,
59-
pageinfo_type: Any = PageInfo,
60-
) -> Connection:
61+
connection_type: ConnectionConstructor = Connection,
62+
edge_type: EdgeConstructor = Edge,
63+
pageinfo_type: PageInfoConstructor = PageInfo,
64+
) -> ConnectionType:
6165
"""Deprecated alias for connection_from_array.
6266
6367
We're now using the JavaScript terminology in Python as well, since list
@@ -84,10 +88,10 @@ def connection_from_array_slice(
8488
slice_start: int = 0,
8589
array_length: int = None,
8690
array_slice_length: int = None,
87-
connection_type: Any = Connection,
88-
edge_type: Any = Edge,
89-
page_info_type: Any = PageInfo,
90-
) -> Connection:
91+
connection_type: ConnectionConstructor = Connection,
92+
edge_type: EdgeConstructor = Edge,
93+
page_info_type: PageInfoConstructor = PageInfo,
94+
) -> ConnectionType:
9195
"""Create a connection object from a slice of the result set.
9296
9397
Note that different from its JavaScript counterpart which expects an array,
@@ -162,13 +166,13 @@ def connection_from_array_slice(
162166
def connection_from_list_slice(
163167
list_slice: Sequence,
164168
args: ConnectionArguments = None,
165-
connection_type: Any = Connection,
166-
edge_type: Any = Edge,
167-
pageinfo_type: Any = PageInfo,
169+
connection_type: ConnectionConstructor = Connection,
170+
edge_type: EdgeConstructor = Edge,
171+
pageinfo_type: PageInfoConstructor = PageInfo,
168172
slice_start=0,
169173
list_length=0,
170174
list_slice_length=None,
171-
) -> Connection:
175+
) -> ConnectionType:
172176
"""Deprecated alias for connection_from_array_slice.
173177
174178
We're now using the JavaScript terminology in Python as well, since list

Diff for: src/graphql_relay/connection/connectiontypes.py

+50
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,8 @@
11
from typing import Any, Dict, List, NamedTuple, Optional
2+
try:
3+
from typing import Protocol
4+
except ImportError:
5+
from typing_extensions import Protocol # type: ignore
26

37
__all__ = ["Connection", "ConnectionArguments", "ConnectionCursor", "Edge", "PageInfo"]
48

@@ -7,6 +11,25 @@
711
ConnectionCursor = str
812

913

14+
class PageInfoType(Protocol):
15+
@property
16+
def startCursor(self) -> Optional[ConnectionCursor]: ...
17+
def endCursor(self) -> Optional[ConnectionCursor]: ...
18+
def hasPreviousPage(self) -> Optional[bool]: ...
19+
def hasNextPage(self) -> Optional[bool]: ...
20+
21+
22+
class PageInfoConstructor(Protocol):
23+
def __call__(
24+
self,
25+
*,
26+
startCursor: Optional[ConnectionCursor],
27+
endCursor: Optional[ConnectionCursor],
28+
hasPreviousPage: Optional[bool],
29+
hasNextPage: Optional[bool],
30+
) -> PageInfoType: ...
31+
32+
1033
class PageInfo(NamedTuple):
1134
"""A type designed to be exposed as `PageInfo` over GraphQL."""
1235

@@ -16,13 +39,40 @@ class PageInfo(NamedTuple):
1639
hasNextPage: Optional[bool]
1740

1841

42+
class EdgeType(Protocol):
43+
@property
44+
def node(self) -> Any: ...
45+
@property
46+
def cursor(self) -> ConnectionCursor: ...
47+
48+
49+
class EdgeConstructor(Protocol):
50+
def __call__(self, *, node: Any, cursor: ConnectionCursor) -> EdgeType: ...
51+
52+
1953
class Edge(NamedTuple):
2054
"""A type designed to be exposed as a `Edge` over GraphQL."""
2155

2256
node: Any
2357
cursor: ConnectionCursor
2458

2559

60+
class ConnectionType(Protocol):
61+
@property
62+
def edges(self): List[EdgeType]: ...
63+
@property
64+
def pageInfo(self): PageInfoType: ...
65+
66+
67+
class ConnectionConstructor(Protocol):
68+
def __call__(
69+
self,
70+
*,
71+
edges: List[EdgeType],
72+
pageInfo: PageInfoType,
73+
) -> ConnectionType: ...
74+
75+
2676
class Connection(NamedTuple):
2777
"""A type designed to be exposed as a `Connection` over GraphQL."""
2878

0 commit comments

Comments
 (0)