|
1 | | -from typing import Any, NamedTuple |
| 1 | +from typing import Any, Dict, List, NamedTuple, Optional |
2 | 2 |
|
3 | 3 | from graphql.type import ( |
4 | 4 | GraphQLArgument, |
|
15 | 15 | Thunk, |
16 | 16 | ) |
17 | 17 |
|
| 18 | +try: |
| 19 | + from typing import Protocol |
| 20 | +except ImportError: # Python < 3.8 |
| 21 | + from typing_extensions import Protocol # type: ignore |
| 22 | + |
18 | 23 | __all__ = [ |
19 | 24 | "connection_definitions", |
20 | 25 | "forward_connection_args", |
21 | 26 | "backward_connection_args", |
22 | 27 | "connection_args", |
| 28 | + "Connection", |
| 29 | + "ConnectionArguments", |
| 30 | + "ConnectionCursor", |
| 31 | + "Edge", |
23 | 32 | "GraphQLConnectionDefinitions", |
| 33 | + "PageInfo", |
24 | 34 | ] |
25 | 35 |
|
26 | 36 |
|
@@ -52,6 +62,22 @@ def resolve_maybe_thunk(thing_or_thunk: Thunk) -> Any: |
52 | 62 | return thing_or_thunk() if callable(thing_or_thunk) else thing_or_thunk |
53 | 63 |
|
54 | 64 |
|
| 65 | +"""A type alias for cursors in this implementation.""" |
| 66 | +ConnectionCursor = str |
| 67 | + |
| 68 | + |
| 69 | +"""A type describing the arguments a connection field receives in GraphQL. |
| 70 | +
|
| 71 | +The following kinds of arguments are expected (all optional): |
| 72 | +
|
| 73 | + before: ConnectionCursor |
| 74 | + after: ConnectionCursor |
| 75 | + first: int |
| 76 | + last: int |
| 77 | +""" |
| 78 | +ConnectionArguments = Dict[str, Any] |
| 79 | + |
| 80 | + |
55 | 81 | def connection_definitions( |
56 | 82 | node_type: GraphQLObjectType, |
57 | 83 | name: str = None, |
@@ -104,6 +130,91 @@ def connection_definitions( |
104 | 130 | return GraphQLConnectionDefinitions(edge_type, connection_type) |
105 | 131 |
|
106 | 132 |
|
| 133 | +class PageInfoType(Protocol): |
| 134 | + @property |
| 135 | + def startCursor(self) -> Optional[ConnectionCursor]: |
| 136 | + ... |
| 137 | + |
| 138 | + def endCursor(self) -> Optional[ConnectionCursor]: |
| 139 | + ... |
| 140 | + |
| 141 | + def hasPreviousPage(self) -> bool: |
| 142 | + ... |
| 143 | + |
| 144 | + def hasNextPage(self) -> bool: |
| 145 | + ... |
| 146 | + |
| 147 | + |
| 148 | +class PageInfoConstructor(Protocol): |
| 149 | + def __call__( |
| 150 | + self, |
| 151 | + *, |
| 152 | + startCursor: Optional[ConnectionCursor], |
| 153 | + endCursor: Optional[ConnectionCursor], |
| 154 | + hasPreviousPage: bool, |
| 155 | + hasNextPage: bool, |
| 156 | + ) -> PageInfoType: |
| 157 | + ... |
| 158 | + |
| 159 | + |
| 160 | +class PageInfo(NamedTuple): |
| 161 | + """A type designed to be exposed as `PageInfo` over GraphQL.""" |
| 162 | + |
| 163 | + startCursor: Optional[ConnectionCursor] |
| 164 | + endCursor: Optional[ConnectionCursor] |
| 165 | + hasPreviousPage: bool |
| 166 | + hasNextPage: bool |
| 167 | + |
| 168 | + |
| 169 | +class EdgeType(Protocol): |
| 170 | + @property |
| 171 | + def node(self) -> Any: |
| 172 | + ... |
| 173 | + |
| 174 | + @property |
| 175 | + def cursor(self) -> ConnectionCursor: |
| 176 | + ... |
| 177 | + |
| 178 | + |
| 179 | +class EdgeConstructor(Protocol): |
| 180 | + def __call__(self, *, node: Any, cursor: ConnectionCursor) -> EdgeType: |
| 181 | + ... |
| 182 | + |
| 183 | + |
| 184 | +class Edge(NamedTuple): |
| 185 | + """A type designed to be exposed as a `Edge` over GraphQL.""" |
| 186 | + |
| 187 | + node: Any |
| 188 | + cursor: ConnectionCursor |
| 189 | + |
| 190 | + |
| 191 | +class ConnectionType(Protocol): |
| 192 | + @property |
| 193 | + def edges(self): |
| 194 | + List[EdgeType]: ... |
| 195 | + |
| 196 | + @property |
| 197 | + def pageInfo(self): |
| 198 | + PageInfoType: ... |
| 199 | + |
| 200 | + |
| 201 | +class ConnectionConstructor(Protocol): |
| 202 | + def __call__( |
| 203 | + self, |
| 204 | + *, |
| 205 | + edges: List[EdgeType], |
| 206 | + pageInfo: PageInfoType, |
| 207 | + ) -> ConnectionType: |
| 208 | + ... |
| 209 | + |
| 210 | + |
| 211 | +class Connection(NamedTuple): |
| 212 | + """A type designed to be exposed as a `Connection` over GraphQL.""" |
| 213 | + |
| 214 | + edges: List[Edge] |
| 215 | + pageInfo: PageInfo |
| 216 | + |
| 217 | + |
107 | 218 | # The common page info type used by all connections. |
108 | 219 | page_info_type = GraphQLObjectType( |
109 | 220 | "PageInfo", |
|
0 commit comments