Skip to content

Commit 3c1de4f

Browse files
Makes classes compatible with mypy 1.2
1 parent 1d9d5c9 commit 3c1de4f

36 files changed

+1312
-1122
lines changed

.github/workflows/test.yml

+2-1
Original file line numberDiff line numberDiff line change
@@ -38,7 +38,8 @@ jobs:
3838
- name: Run tests
3939
run: |
4040
poetry run flake8 .
41-
poetry run mypy classes ./tests/**/*.py
41+
# TODO: Remove `no-warn-unused-ignores` flag once we drop support for Python 3.7 and 3.8
42+
poetry run mypy --no-warn-unused-ignores classes ./tests/**/*.py
4243
poetry run codespell classes tests docs typesafety README.md CONTRIBUTING.md CHANGELOG.md
4344
poetry run pytest classes tests docs/pages README.md
4445
poetry run doc8 -q docs

CHANGELOG.md

+5
Original file line numberDiff line numberDiff line change
@@ -2,6 +2,11 @@
22

33
We follow Semantic Versions since the `0.1.0` release.
44

5+
## Version 0.5.0 WIP
6+
7+
### Features
8+
9+
- Now requires `mypy>=1.2`
510

611
## Version 0.4.1
712

classes/_typeclass.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -379,7 +379,7 @@ def __call__(
379379
],
380380
*args,
381381
**kwargs,
382-
) -> _ReturnType:
382+
) -> _ReturnType: # type: ignore[type-var]
383383
"""
384384
We use this method to actually call a typeclass.
385385

classes/contrib/mypy/typeops/call_signatures.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -6,10 +6,10 @@
66
from mypy.typeops import get_type_vars, make_simplified_union
77
from mypy.types import CallableType, Instance, ProperType
88
from mypy.types import Type as MypyType
9-
from mypy.types import TypeVarType, union_items
9+
from mypy.types import TypeVarType
1010
from typing_extensions import Final, final
1111

12-
from classes.contrib.mypy.typeops import type_loader
12+
from classes.contrib.mypy.typeops import type_loader, union
1313

1414
_INCOMPATIBLE_TYPEVAR_MSG: Final = (
1515
'Argument 1 to {0} has incompatible type "{1}"; expected "{2}"'
@@ -61,7 +61,7 @@ def _infer_type_var(
6161
first_arg: TypeVarType,
6262
passed_type: MypyType,
6363
) -> CallableType:
64-
instance_types = union_items(self._instance_type)
64+
instance_types = union.union_items(self._instance_type)
6565
if isinstance(self._associated_type, Instance):
6666
instance_types.append(_load_supports_type(
6767
first_arg,

classes/contrib/mypy/typeops/mro.py

+4-4
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,10 @@
44
from mypy.subtypes import is_equivalent
55
from mypy.types import Instance
66
from mypy.types import Type as MypyType
7-
from mypy.types import UnionType, union_items
7+
from mypy.types import UnionType
88
from typing_extensions import final
99

10-
from classes.contrib.mypy.typeops import type_loader
10+
from classes.contrib.mypy.typeops import type_loader, union
1111

1212

1313
@final
@@ -78,7 +78,7 @@ def __init__(
7878
"""
7979
self._associated_type = associated_type
8080
self._ctx = ctx
81-
self._instance_types = union_items(instance_type)
81+
self._instance_types = union.union_items(instance_type)
8282

8383
# Why do we store added types in a mutable global state?
8484
# Because, these types are hard to replicate without the proper context.
@@ -181,7 +181,7 @@ def _remove_unified_type(
181181
base = instance_type.type.bases[index]
182182
union_types = [
183183
type_arg
184-
for type_arg in union_items(base.args[0])
184+
for type_arg in union.union_items(base.args[0])
185185
if type_arg not in supports_type.args
186186
]
187187
instance_type.type.bases[index] = supports_type.copy_modified(

classes/contrib/mypy/typeops/type_loader.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@ def load_supports_type(
2323
[arg_type],
2424
)
2525
assert supports_spec
26-
supports_spec.type._promote = None # noqa: WPS437
26+
supports_spec.type._promote = [] # noqa: WPS437
2727
return supports_spec
2828

2929

classes/contrib/mypy/typeops/union.py

+13
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,13 @@
1+
from typing import List
2+
3+
from mypy.types import ProperType
4+
from mypy.types import Type as MypyType
5+
from mypy.types import flatten_nested_unions, get_proper_type
6+
7+
8+
def union_items(typ: MypyType) -> List[ProperType]:
9+
"""Get and flat all union types."""
10+
return [
11+
get_proper_type(union_member)
12+
for union_member in flatten_nested_unions([typ])
13+
]

classes/contrib/mypy/validation/validate_instance/validate_runtime.py

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

33
from mypy.erasetype import erase_type
44
from mypy.plugin import MethodContext
5-
from mypy.sametypes import is_same_type
6-
from mypy.subtypes import is_subtype
5+
from mypy.subtypes import is_same_type, is_subtype
76
from mypy.types import Instance
87
from mypy.types import Type as MypyType
98
from mypy.types import TypedDictType

poetry.lock

+1,113-953
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

pyproject.toml

+3-3
Original file line numberDiff line numberDiff line change
@@ -48,18 +48,18 @@ python = "^3.7"
4848
typing_extensions = ">=3.10,<5.0"
4949

5050
[tool.poetry.dev-dependencies]
51-
mypy = "^0.942"
51+
mypy = "^1.2.0"
5252

5353
wemake-python-styleguide = "^0.17"
5454
flake8-pytest-style = "^1.6"
55-
nitpick = "^0.32"
55+
nitpick = "^0.33.1"
5656

5757
safety = "^2.3"
5858

5959
pytest = "^7.2"
6060
pytest-cov = "^4.0"
6161
pytest-randomly = "^3.12"
62-
pytest-mypy-plugins = "^1.9"
62+
pytest-mypy-plugins = "^1.10.1"
6363

6464
sphinx = "^5.2"
6565
sphinx-autodoc-typehints = "^1.20"

setup.cfg

+2
Original file line numberDiff line numberDiff line change
@@ -91,6 +91,8 @@ exclude_lines =
9191
plugins =
9292
classes.contrib.mypy.classes_plugin
9393

94+
disable_error_code = empty-body
95+
9496
allow_redefinition = false
9597
check_untyped_defs = true
9698
disallow_any_explicit = true

tests/test_associated_type/test_variadic_generic.py

+3-3
Original file line numberDiff line numberDiff line change
@@ -31,6 +31,6 @@ def test_subtype_is_variadic():
3131
class Example(AssociatedType[_FirstType]):
3232
"""Correct type."""
3333

34-
assert Example[int]
35-
assert Example[int, int] # type: ignore
36-
assert Example[int, int, str] # type: ignore
34+
assert Example[int] # type: ignore[truthy-function]
35+
assert Example[int, int] # type: ignore[misc]
36+
assert Example[int, int, str] # type: ignore[misc]

tests/test_supports.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __instancecheck__(cls, other) -> bool:
1414
)
1515

1616

17-
class _ListOfStr(List[str], metaclass=_ListOfStrMeta):
17+
class _ListOfStr(List[str], metaclass=_ListOfStrMeta): # type: ignore[misc]
1818
"""We use this for testing concrete type calls."""
1919

2020

tests/test_typeclass/test_call.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,7 +14,7 @@ def __instancecheck__(cls, other) -> bool:
1414
)
1515

1616

17-
class _ListOfStr(List[str], metaclass=_ListOfStrMeta):
17+
class _ListOfStr(List[str], metaclass=_ListOfStrMeta): # type: ignore[misc]
1818
"""We use this for testing concrete type calls."""
1919

2020

tests/test_typeclass/test_typed_dict.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ def __instancecheck__(cls, arg: object) -> bool:
2222

2323
_Meta = type('_Meta', (_UserDictMeta, type(TypedDict)), {})
2424

25-
class UserDict(_User, metaclass=_Meta):
25+
class UserDict(_User, metaclass=_Meta): # type: ignore[misc]
2626
"""We use this class to represent a typed dict with instance check."""
2727

2828
@typeclass

typesafety/test_associated_type/test_validation/test_base_classes.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@
1010
def to_json(instance, verbose: bool = False) -> str:
1111
...
1212
out: |
13-
main:6: error: Single direct subclass of "classes._typeclass.AssociatedType" required; got "main.ToJson"
13+
main:6: error: Single direct subclass of "classes._typeclass.AssociatedType" required; got "main.ToJson" [misc]
1414
1515
1616
- case: typeclass_definied_by_multiple_parents
@@ -28,4 +28,4 @@
2828
def to_json(instance, verbose: bool = False) -> str:
2929
...
3030
out: |
31-
main:9: error: Single direct subclass of "classes._typeclass.AssociatedType" required; got "main.ToJson"
31+
main:9: error: Single direct subclass of "classes._typeclass.AssociatedType" required; got "main.ToJson" [misc]

typesafety/test_associated_type/test_validation/test_bodies.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@
1111
def compare(instance) -> int:
1212
...
1313
out: |
14-
main:7: error: Associated types must not have bodies
14+
main:7: error: Associated types must not have bodies [misc]
1515
1616
1717
- case: associated_type_with_attr
@@ -26,7 +26,7 @@
2626
def compare(instance) -> int:
2727
...
2828
out: |
29-
main:6: error: Associated types must not have bodies
29+
main:6: error: Associated types must not have bodies [misc]
3030
3131
3232
- case: associated_type_with_pass

typesafety/test_associated_type/test_validation/test_generic_missmatch.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
def compare(instance: List[X]) -> X:
1515
...
1616
out: |
17-
main:10: error: Generic type "main.Compare" with "0" type arguments does not match generic instance declaration "builtins.list[X`-1]" with "1" type arguments
17+
main:10: error: Generic type "main.Compare" with "0" type arguments does not match generic instance declaration "builtins.list[X`-1]" with "1" type arguments [misc]

typesafety/test_associated_type/test_validation/test_reuse.yml

+1-1
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,4 @@
1414
def from_json(instance) -> str:
1515
...
1616
out: |
17-
main:10: error: AssociatedType "main.ToJson" must not be reused, originally associated with "main.from_json"
17+
main:10: error: AssociatedType "main.ToJson" must not be reused, originally associated with "main.from_json" [misc]

typesafety/test_associated_type/test_variadic.yml

+2-2
Original file line numberDiff line numberDiff line change
@@ -21,5 +21,5 @@
2121
One[int, str]
2222
Two[int]
2323
out: |
24-
main:18: error: Type application has too many types (1 expected)
25-
main:19: error: Type application has too few types (2 expected)
24+
main:18: error: Type application has too many types (1 expected) [misc]
25+
main:19: error: Type application has too few types (2 expected) [misc]

typesafety/test_supports_type/test_generic.yml

+13-13
Original file line numberDiff line numberDiff line change
@@ -20,8 +20,8 @@
2020
2121
x: Supports[Some[int]] = [1, 2, 3]
2222
y = {1, 2, 3}
23-
reveal_type(some(x)) # N: Revealed type is "builtins.int*"
24-
reveal_type(some(y)) # N: Revealed type is "builtins.int*"
23+
reveal_type(some(x)) # N: Revealed type is "builtins.int"
24+
reveal_type(some(y)) # N: Revealed type is "builtins.int"
2525
2626
2727
- case: supports_generic_correct2
@@ -47,8 +47,8 @@
4747
4848
x: Supports[Some[int, str]] = {1: 'a'}
4949
50-
reveal_type(some(x, 1, 'a')) # N: Revealed type is "builtins.str*"
51-
reveal_type(some({'a': 1}, 'a', 1)) # N: Revealed type is "builtins.int*"
50+
reveal_type(some(x, 1, 'a')) # N: Revealed type is "builtins.str"
51+
reveal_type(some({'a': 1}, 'a', 1)) # N: Revealed type is "builtins.int"
5252
5353
5454
- case: supports_generic_wrong1
@@ -73,8 +73,8 @@
7373
x: Supports[Some[int]] = {1, 2, 3}
7474
some({1, 2, 3})
7575
out: |
76-
main:17: error: Incompatible types in assignment (expression has type "Set[int]", variable has type "Supports[Some[int]]")
77-
main:18: error: Argument 1 to "some" has incompatible type "Set[int]"; expected "Supports[Some[<nothing>]]"
76+
main:17: error: Incompatible types in assignment (expression has type "Set[int]", variable has type "Supports[Some[int]]") [assignment]
77+
main:18: error: Argument 1 to "some" has incompatible type "Set[int]"; expected "Supports[Some[<nothing>]]" [arg-type]
7878
7979
8080
- case: supports_generic_wrong2
@@ -105,11 +105,11 @@
105105
y: Supports[Some[int]] = {1, 2, 3}
106106
z: Supports[Some[int]] = 1
107107
out: |
108-
main:17: error: Found different typeclass ".instance" calls, use only "main.some"
109-
main:17: error: Instance "Union[builtins.list[X`-1], builtins.set[X`-1]]" does not match inferred type "builtins.set[_T`1]"
110-
main:22: error: Incompatible types in assignment (expression has type "List[int]", variable has type "Supports[Some[int]]")
111-
main:23: error: Incompatible types in assignment (expression has type "Set[int]", variable has type "Supports[Some[int]]")
112-
main:24: error: Incompatible types in assignment (expression has type "int", variable has type "Supports[Some[int]]")
108+
main:17: error: Found different typeclass ".instance" calls, use only "main.some" [misc]
109+
main:17: error: Instance "Union[builtins.list[X`-1], builtins.set[X`-1]]" does not match inferred type "builtins.set[_T`1]" [misc]
110+
main:22: error: Incompatible types in assignment (expression has type "List[int]", variable has type "Supports[Some[int]]") [assignment]
111+
main:23: error: Incompatible types in assignment (expression has type "Set[int]", variable has type "Supports[Some[int]]") [assignment]
112+
main:24: error: Incompatible types in assignment (expression has type "int", variable has type "Supports[Some[int]]") [assignment]
113113
114114
115115
- case: supports_multiple_one_generic_one_regular
@@ -177,5 +177,5 @@
177177
...
178178
179179
a: Supports[Some[str], Other[int]]
180-
reveal_type(some(a)) # N: Revealed type is "builtins.str*"
181-
reveal_type(other(a)) # N: Revealed type is "builtins.int*"
180+
reveal_type(some(a)) # N: Revealed type is "builtins.str"
181+
reveal_type(other(a)) # N: Revealed type is "builtins.int"

typesafety/test_supports_type/test_regular.yml

+9-9
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
2424
convert_to_json(1)
2525
convert_to_json('a')
26-
convert_to_json(None) # E: Argument 1 to "convert_to_json" has incompatible type "None"; expected "Supports[ToJson]"
26+
convert_to_json(None) # E: Argument 1 to "convert_to_json" has incompatible type "None"; expected "Supports[ToJson]" [arg-type]
2727
2828
2929
- case: typeclass_supports_type_restriction
@@ -74,7 +74,7 @@
7474
7575
convert_to_json(to_json, 1)
7676
convert_to_json(to_json, 'a')
77-
convert_to_json(to_json, None) # E: Argument 2 to "convert_to_json" has incompatible type "None"; expected "Supports[ToJson]"
77+
convert_to_json(to_json, None) # E: Argument 2 to "convert_to_json" has incompatible type "None"; expected "Supports[ToJson]" [arg-type]
7878
7979
8080
- case: typeclass_supports_with_function
@@ -97,7 +97,7 @@
9797
def convert_to_json(instance: Supports[to_json]) -> str:
9898
...
9999
out: |
100-
main:15: error: Function "main.to_json" is not valid as a type
100+
main:15: error: Function "main.to_json" is not valid as a type [valid-type]
101101
main:15: note: Perhaps you need "Callable[...]" or a callback protocol?
102102
103103
@@ -119,7 +119,7 @@
119119
def convert_to_json(instance: Supports[Other]) -> str:
120120
return to_json(instance)
121121
out: |
122-
main:14: error: Argument 1 to "to_json" has incompatible type "Supports[Other]"; expected "Supports[ToJson]"
122+
main:14: error: Argument 1 to "to_json" has incompatible type "Supports[Other]"; expected "Supports[ToJson]" [arg-type]
123123
124124
125125
- case: supports_annotation
@@ -139,20 +139,20 @@
139139
return str(instance)
140140
141141
a: Supports[ToJson] = 1
142-
b: Supports[ToJson] = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "Supports[ToJson]")
142+
b: Supports[ToJson] = 'a' # E: Incompatible types in assignment (expression has type "str", variable has type "Supports[ToJson]") [assignment]
143143
144144
145145
- case: supports_type_bound
146146
disable_cache: false
147147
main: |
148148
from classes import Supports, AssociatedType
149149
150-
a: Supports[int] # E: Type argument "builtins.int" of "Supports" must be a subtype of "classes._typeclass.AssociatedType"
150+
a: Supports[int] # E: Type argument "builtins.int" of "Supports" must be a subtype of "classes._typeclass.AssociatedType" [misc]
151151
152152
class A(AssociatedType):
153153
...
154154
155-
b: Supports[A, int] # E: Type argument "builtins.int" of "Supports" must be a subtype of "classes._typeclass.AssociatedType"
155+
b: Supports[A, int] # E: Type argument "builtins.int" of "Supports" must be a subtype of "classes._typeclass.AssociatedType" [misc]
156156
157157
158158
- case: supports_multiple_types
@@ -261,5 +261,5 @@
261261
a: Supports[ToJson] = 'a'
262262
b: Supports[FromJson] = 'a' # error
263263
out: |
264-
main:21: error: Instance callback is incompatible "def (instance: builtins.str, other: Any) -> builtins.str"; expected "def (instance: builtins.str) -> builtins.str"
265-
main:26: error: Incompatible types in assignment (expression has type "str", variable has type "Supports[FromJson]")
264+
main:21: error: Instance callback is incompatible "def (instance: builtins.str, other: Any) -> builtins.str"; expected "def (instance: builtins.str) -> builtins.str" [misc]
265+
main:26: error: Incompatible types in assignment (expression has type "str", variable has type "Supports[FromJson]") [assignment]

typesafety/test_typeclass/test__call__.yml

+4-4
Original file line numberDiff line numberDiff line change
@@ -63,7 +63,7 @@
6363
some(B()) # ok
6464
some(C()) # ok
6565
out: |
66-
main:20: error: Argument 1 to "some" has incompatible type "A"; expected "B"
66+
main:20: error: Argument 1 to "some" has incompatible type "A"; expected "B" [arg-type]
6767
6868
6969
- case: typeclass_call_generic_instance_variance
@@ -98,7 +98,7 @@
9898
some(b) # ok
9999
some(c) # ok
100100
out: |
101-
main:26: error: Argument 1 to "some" has incompatible type "A[int]"; expected "B[<nothing>]"
101+
main:26: error: Argument 1 to "some" has incompatible type "A[int]"; expected "B[<nothing>]" [arg-type]
102102
103103
104104
- case: typeclass_call_variance_union1
@@ -129,7 +129,7 @@
129129
some(B()) # ok
130130
some(C()) # ok
131131
out: |
132-
main:22: error: Argument 1 to "some" has incompatible type "A"; expected "B"
132+
main:22: error: Argument 1 to "some" has incompatible type "A"; expected "B" [arg-type]
133133
134134
135135
- case: typeclass_call_variance_union2
@@ -238,4 +238,4 @@
238238
def some(instance) -> int:
239239
...
240240
241-
some() # E: Missing positional argument "instance" in call to "__call__" of "_TypeClass"
241+
some() # E: Missing positional argument "instance" in call to "__call__" of "_TypeClass" [call-arg]

0 commit comments

Comments
 (0)