Skip to content

Commit bb5f935

Browse files
committed
Make type hints more strict
1 parent 3be10e8 commit bb5f935

13 files changed

+74
-57
lines changed

Diff for: mypy.ini

+8-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,11 @@
11
[mypy]
22
python_version = 3.9
3-
warn_redundant_casts = true
3+
check_untyped_defs = True
4+
no_implicit_optional = True
5+
strict_optional = True
6+
warn_redundant_casts = True
47
warn_unused_ignores = True
8+
disallow_untyped_defs = True
9+
10+
[mypy-tests.*]
11+
disallow_untyped_defs = False

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

+12-10
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __len__(self) -> int:
4343

4444
def connection_from_array(
4545
data: SizedSliceable,
46-
args: ConnectionArguments = None,
46+
args: Optional[ConnectionArguments] = None,
4747
connection_type: ConnectionConstructor = Connection,
4848
edge_type: EdgeConstructor = Edge,
4949
page_info_type: PageInfoConstructor = PageInfo,
@@ -73,7 +73,7 @@ def connection_from_array(
7373

7474
def connection_from_list(
7575
data: Sequence,
76-
args: ConnectionArguments = None,
76+
args: Optional[ConnectionArguments] = None,
7777
connection_type: ConnectionConstructor = Connection,
7878
edge_type: EdgeConstructor = Edge,
7979
pageinfo_type: PageInfoConstructor = PageInfo,
@@ -100,10 +100,10 @@ def connection_from_list(
100100

101101
def connection_from_array_slice(
102102
array_slice: SizedSliceable,
103-
args: ConnectionArguments = None,
103+
args: Optional[ConnectionArguments] = None,
104104
slice_start: int = 0,
105-
array_length: int = None,
106-
array_slice_length: int = None,
105+
array_length: Optional[int] = None,
106+
array_slice_length: Optional[int] = None,
107107
connection_type: ConnectionConstructor = Connection,
108108
edge_type: EdgeConstructor = Edge,
109109
page_info_type: PageInfoConstructor = PageInfo,
@@ -181,13 +181,13 @@ def connection_from_array_slice(
181181

182182
def connection_from_list_slice(
183183
list_slice: Sequence,
184-
args: ConnectionArguments = None,
184+
args: Optional[ConnectionArguments] = None,
185185
connection_type: ConnectionConstructor = Connection,
186186
edge_type: EdgeConstructor = Edge,
187187
pageinfo_type: PageInfoConstructor = PageInfo,
188-
slice_start=0,
189-
list_length=0,
190-
list_slice_length=None,
188+
slice_start: int = 0,
189+
list_length: int = 0,
190+
list_slice_length: Optional[int] = None,
191191
) -> ConnectionType:
192192
"""Deprecated alias for connection_from_array_slice.
193193
@@ -256,7 +256,9 @@ def cursor_for_object_in_connection(
256256
return offset_to_cursor(offset)
257257

258258

259-
def get_offset_with_default(cursor: ConnectionCursor = None, default_offset=0) -> int:
259+
def get_offset_with_default(
260+
cursor: Optional[ConnectionCursor] = None, default_offset: int = 0
261+
) -> int:
260262
"""Get offset from a given cursor and a default.
261263
262264
Given an optional cursor and a default offset, return the offset to use;

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

+15-13
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
1-
from typing import Any, Dict, List, NamedTuple, Optional
1+
from typing import Any, Dict, List, NamedTuple, Optional, Union
22

3-
from graphql.type import (
3+
from graphql import (
4+
get_named_type,
45
GraphQLArgument,
56
GraphQLArgumentMap,
67
GraphQLBoolean,
@@ -9,6 +10,7 @@
910
GraphQLFieldResolver,
1011
GraphQLInt,
1112
GraphQLList,
13+
GraphQLNamedOutputType,
1214
GraphQLNonNull,
1315
GraphQLObjectType,
1416
GraphQLString,
@@ -92,18 +94,18 @@ def resolve_maybe_thunk(thing_or_thunk: Thunk) -> Any:
9294

9395

9496
def connection_definitions(
95-
node_type: GraphQLObjectType,
96-
name: str = None,
97-
resolve_node: GraphQLFieldResolver = None,
98-
resolve_cursor: GraphQLFieldResolver = None,
99-
edge_fields: Thunk[GraphQLFieldMap] = None,
100-
connection_fields: Thunk[GraphQLFieldMap] = None,
97+
node_type: Union[GraphQLNamedOutputType, GraphQLNonNull[GraphQLNamedOutputType]],
98+
name: Optional[str] = None,
99+
resolve_node: Optional[GraphQLFieldResolver] = None,
100+
resolve_cursor: Optional[GraphQLFieldResolver] = None,
101+
edge_fields: Optional[Thunk[GraphQLFieldMap]] = None,
102+
connection_fields: Optional[Thunk[GraphQLFieldMap]] = None,
101103
) -> GraphQLConnectionDefinitions:
102104
"""Return GraphQLObjectTypes for a connection with the given name.
103105
104106
The nodes of the returned object types will be of the specified type.
105107
"""
106-
name = name or node_type.name
108+
name = name or get_named_type(node_type).name
107109
edge_fields = edge_fields or {}
108110
connection_fields = connection_fields or {}
109111

@@ -203,12 +205,12 @@ class Edge(NamedTuple):
203205

204206
class ConnectionType(Protocol):
205207
@property
206-
def edges(self):
207-
List[EdgeType]: ...
208+
def edges(self) -> List[EdgeType]:
209+
...
208210

209211
@property
210-
def pageInfo(self):
211-
PageInfoType: ...
212+
def pageInfo(self) -> PageInfoType:
213+
...
212214

213215

214216
class ConnectionConstructor(Protocol):

Diff for: src/graphql_relay/mutation/mutation.py

+15-11
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
from inspect import iscoroutinefunction
2-
from typing import Any, Callable
2+
from typing import Any, Callable, Dict, Optional
33

4-
from graphql.error import GraphQLError
5-
from graphql.pyutils import AwaitableOrValue, inspect
6-
from graphql.type import (
4+
from graphql import (
5+
GraphQLError,
76
GraphQLArgument,
87
GraphQLField,
98
GraphQLFieldMap,
@@ -16,7 +15,7 @@
1615
GraphQLString,
1716
Thunk,
1817
)
19-
18+
from graphql.pyutils import AwaitableOrValue, inspect
2019

2120
# Note: Contrary to the Javascript implementation of MutationFn,
2221
# the context is passed as part of the GraphQLResolveInfo and any arguments
@@ -32,7 +31,7 @@ def resolve_maybe_thunk(thing_or_thunk: Thunk) -> Any:
3231

3332

3433
class NullResult:
35-
def __init__(self, clientMutationId=None):
34+
def __init__(self, clientMutationId: Optional[str] = None) -> None:
3635
self.clientMutationId = clientMutationId
3736

3837

@@ -41,8 +40,9 @@ def mutation_with_client_mutation_id(
4140
input_fields: Thunk[GraphQLInputFieldMap],
4241
output_fields: Thunk[GraphQLFieldMap],
4342
mutate_and_get_payload: MutationFn,
44-
description: str = None,
45-
deprecation_reason: str = None,
43+
description: Optional[str] = None,
44+
deprecation_reason: Optional[str] = None,
45+
extensions: Optional[Dict[str, Any]] = None,
4646
) -> GraphQLField:
4747
"""
4848
Returns a GraphQLFieldConfig for the specified mutation.
@@ -78,7 +78,7 @@ def augmented_output_fields() -> GraphQLFieldMap:
7878
if iscoroutinefunction(mutate_and_get_payload):
7979

8080
# noinspection PyShadowingBuiltins
81-
async def resolve(_root, info, input):
81+
async def resolve(_root: Any, info: GraphQLResolveInfo, input: Dict) -> Any:
8282
payload = await mutate_and_get_payload(info, **input)
8383
try:
8484
clientMutationId = input["clientMutationId"]
@@ -95,7 +95,10 @@ async def resolve(_root, info, input):
9595

9696
else:
9797

98-
def resolve(_root, info, input):
98+
# noinspection PyShadowingBuiltins
99+
def resolve( # type: ignore
100+
_root: Any, info: GraphQLResolveInfo, input: Dict
101+
) -> Any:
99102
payload = mutate_and_get_payload(info, **input)
100103
try:
101104
clientMutationId = input["clientMutationId"]
@@ -107,7 +110,7 @@ def resolve(_root, info, input):
107110
if payload is None:
108111
payload = NullResult(clientMutationId)
109112
else:
110-
payload.clientMutationId = clientMutationId
113+
payload.clientMutationId = clientMutationId # type: ignore
111114
return payload
112115

113116
return GraphQLField(
@@ -116,4 +119,5 @@ def resolve(_root, info, input):
116119
deprecation_reason=deprecation_reason,
117120
args={"input": GraphQLArgument(GraphQLNonNull(input_type))},
118121
resolve=resolve,
122+
extensions=extensions,
119123
)

Diff for: src/graphql_relay/node/node.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,8 @@
1-
from typing import Any, Callable, NamedTuple
1+
from typing import Any, Callable, NamedTuple, Optional
22

33
from graphql_relay.utils.base64 import base64, unbase64
44

5-
from graphql.type import (
5+
from graphql import (
66
GraphQLArgument,
77
GraphQLNonNull,
88
GraphQLID,
@@ -23,7 +23,7 @@ class GraphQLNodeDefinitions(NamedTuple):
2323

2424
def node_definitions(
2525
id_fetcher: Callable[[str, GraphQLResolveInfo], Any],
26-
type_resolver: GraphQLTypeResolver = None,
26+
type_resolver: Optional[GraphQLTypeResolver] = None,
2727
) -> GraphQLNodeDefinitions:
2828
"""
2929
Given a function to map from an ID to an underlying object, and a function
@@ -96,7 +96,8 @@ def from_global_id(global_id: str) -> ResolvedGlobalId:
9696

9797

9898
def global_id_field(
99-
type_name: str = None, id_fetcher: Callable[[Any, GraphQLResolveInfo], str] = None
99+
type_name: Optional[str] = None,
100+
id_fetcher: Optional[Callable[[Any, GraphQLResolveInfo], str]] = None,
100101
) -> GraphQLField:
101102
"""
102103
Creates the configuration for an id field on a node, using `to_global_id` to

Diff for: src/graphql_relay/node/plural.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
from typing import Any, Callable
1+
from typing import Any, Callable, List, Optional
22

3-
from graphql.type import (
3+
from graphql import (
44
GraphQLArgument,
55
GraphQLField,
66
GraphQLInputType,
@@ -17,9 +17,9 @@ def plural_identifying_root_field(
1717
input_type: GraphQLInputType,
1818
output_type: GraphQLOutputType,
1919
resolve_single_input: Callable[[GraphQLResolveInfo, str], Any],
20-
description: str = None,
20+
description: Optional[str] = None,
2121
) -> GraphQLField:
22-
def resolve(_obj, info, **args):
22+
def resolve(_obj: Any, info: GraphQLResolveInfo, **args: Any) -> List:
2323
inputs = args[arg_name]
2424
return [resolve_single_input(info, input_) for input_ in inputs]
2525

Diff for: src/graphql_relay/version.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,7 @@ def from_str(cls, v: str) -> "VersionInfo":
3535
serial = int(serial) if serial else 0
3636
return cls(major, minor, micro, level, serial)
3737

38-
def __str__(self):
38+
def __str__(self) -> str:
3939
v = f"{self.major}.{self.minor}.{self.micro}"
4040
level = self.releaselevel
4141
if level and level != "final":

Diff for: tests/connection/test_array_connection.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -739,10 +739,10 @@ def uses_array_slice_length_instead_of_len_function():
739739
class LettersWithoutLen:
740740
__getitem__ = letters.__getitem__
741741

742-
letters_without_len = LettersWithoutLen()
742+
letters_without_len = cast(Sequence, LettersWithoutLen())
743743

744744
with raises(TypeError):
745-
len(cast(Sequence, letters_without_len))
745+
len(letters_without_len)
746746

747747
with raises(TypeError):
748748
connection_from_array_slice(letters_without_len)

Diff for: tests/connection/test_connection.py

+5-4
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,7 @@
55
print_schema,
66
GraphQLField,
77
GraphQLInt,
8+
GraphQLNonNull,
89
GraphQLObjectType,
910
GraphQLSchema,
1011
GraphQLString,
@@ -66,7 +67,7 @@ class User(NamedTuple):
6667
)
6768

6869
friend_connection = connection_definitions(
69-
user_type,
70+
GraphQLNonNull(user_type),
7071
name="Friend",
7172
resolve_node=lambda edge, _info: all_users[edge.node],
7273
edge_fields=lambda: {
@@ -83,7 +84,7 @@ class User(NamedTuple):
8384

8485

8586
user_connection = connection_definitions(
86-
user_type, resolve_node=lambda edge, _info: all_users[edge.node]
87+
GraphQLNonNull(user_type), resolve_node=lambda edge, _info: all_users[edge.node]
8788
).connection_type
8889

8990

@@ -245,7 +246,7 @@ def generates_correct_types():
245246
"""An edge in a connection."""
246247
type FriendEdge {
247248
"""The item at the end of the edge"""
248-
node: User
249+
node: User!
249250
250251
"""A cursor for use in pagination"""
251252
cursor: String!
@@ -264,7 +265,7 @@ def generates_correct_types():
264265
"""An edge in a connection."""
265266
type UserEdge {
266267
"""The item at the end of the edge"""
267-
node: User
268+
node: User!
268269
269270
"""A cursor for use in pagination"""
270271
cursor: String!

Diff for: tests/node/test_global.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from pytest import fixture
44

5-
from graphql import graphql_sync
6-
from graphql.type import (
5+
from graphql import (
6+
graphql_sync,
77
GraphQLField,
88
GraphQLList,
99
GraphQLInt,

Diff for: tests/node/test_node_async.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -2,8 +2,8 @@
22

33
from pytest import mark
44

5-
from graphql import graphql
6-
from graphql.type import (
5+
from graphql import (
6+
graphql,
77
GraphQLField,
88
GraphQLID,
99
GraphQLNonNull,

Diff for: tests/star_wars_schema.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
from graphql.type import (
1+
from graphql import (
22
GraphQLID,
33
GraphQLNonNull,
44
GraphQLObjectType,

Diff for: tests/test_version.py

+2-2
Original file line numberDiff line numberDiff line change
@@ -70,7 +70,7 @@ def version_has_correct_format():
7070
def version_info_has_correct_fields():
7171
assert isinstance(version_info, tuple)
7272
assert str(version_info) == version
73-
groups = _re_version.match(version).groups()
73+
groups = _re_version.match(version).groups() # type: ignore
7474
assert version_info.major == int(groups[0])
7575
assert version_info.minor == int(groups[1])
7676
assert version_info.micro == int(groups[2])
@@ -96,7 +96,7 @@ def version_js_has_correct_format():
9696
def version_info_js_has_correct_fields():
9797
assert isinstance(version_info_js, tuple)
9898
assert str(version_info_js) == version_js
99-
groups = _re_version.match(version_js).groups()
99+
groups = _re_version.match(version_js).groups() # type: ignore
100100
assert version_info_js.major == int(groups[0])
101101
assert version_info_js.minor == int(groups[1])
102102
assert version_info_js.micro == int(groups[2])

0 commit comments

Comments
 (0)