Skip to content

Commit b91ffab

Browse files
committed
Closes #228
1 parent e148db9 commit b91ffab

File tree

3 files changed

+41
-2
lines changed

3 files changed

+41
-2
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,8 @@ We follow Semantic Versions since the `0.1.0` release.
99

1010
- **Breaking**: drops `python3.6` support
1111
- **Breaking**: now requires `typing_extensions>=3.10` and `mypy>=0.902`
12+
- **Breaking**: now `classes` traverses `mro` of registered types
13+
and fallbacks to super-types if some type is not registered
1214
- Adds generic typeclasses
1315
- Adds better typeclass validation during `mypy` typechecking
1416
- Adds `.supports()` method to typeclass to check

classes/contrib/mypy/validation/validate_runtime.py

Lines changed: 20 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,10 @@
3434
'Runtime type "{0}" has unbound type, use implicit any'
3535
)
3636

37+
_TUPLE_LENGTH_MSG: Final = (
38+
'Expected variadic tuple "Tuple[{0}, ...]", got "{1}"'
39+
)
40+
3741

3842
class _RuntimeValidationContext(NamedTuple):
3943
runtime_type: MypyType
@@ -85,7 +89,8 @@ def check_instance_definition(
8589

8690
return _RuntimeValidationContext(runtime_type, is_protocol, all([
8791
_check_runtime_protocol(runtime_type, ctx, is_protocol=is_protocol),
88-
_check_concrete_generics(instance_type, runtime_type, ctx),
92+
_check_concrete_generics(runtime_type, instance_type, ctx),
93+
_check_tuple_size(instance_type, ctx),
8994
protocol_arg_check,
9095
instance_check,
9196
]))
@@ -128,8 +133,8 @@ def _check_runtime_protocol(
128133

129134

130135
def _check_concrete_generics(
131-
instance_type: MypyType,
132136
runtime_type: MypyType,
137+
instance_type: MypyType,
133138
ctx: MethodContext,
134139
) -> bool:
135140
has_concrete_type = False
@@ -152,3 +157,16 @@ def _check_concrete_generics(
152157
ctx.api.fail(_UNBOUND_TYPE_MSG.format(runtime_type), ctx.context)
153158
return False
154159
return not has_concrete_type
160+
161+
162+
def _check_tuple_size(
163+
instance_type: MypyType,
164+
ctx: MethodContext,
165+
) -> bool:
166+
if isinstance(instance_type, TupleType):
167+
ctx.api.fail(
168+
_TUPLE_LENGTH_MSG.format(instance_type.items[0], instance_type),
169+
ctx.context,
170+
)
171+
return False
172+
return True

typesafety/test_typeclass/test_generics/test_generics_regular.yml

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -253,3 +253,22 @@
253253
out: |
254254
main:9: error: Generic type "main.Copy" with "0" type arguments does not match generic instance declaration "typing.Iterable[X`-1]" with "1" type arguments
255255
main:23: note: Revealed type is "<nothing>"
256+
257+
258+
- case: typeclass_generic_tuple
259+
disable_cache: false
260+
main: |
261+
from typing import Iterable, Tuple, TypeVar
262+
from classes import typeclass
263+
264+
X = TypeVar('X')
265+
266+
@typeclass
267+
def some(instance: Iterable[X]) -> X:
268+
...
269+
270+
@some.instance(tuple)
271+
def _some_tuple(instance: Tuple[X, X]) -> X:
272+
...
273+
out: |
274+
main:10: error: Expected variadic tuple "Tuple[X`-1, ...]", got "Tuple[X`-1, X`-1]"

0 commit comments

Comments
 (0)