Skip to content

Commit d80bac8

Browse files
committed
Fixes bug with ABC instances, annotates tests
1 parent c59c4a5 commit d80bac8

File tree

13 files changed

+48
-18
lines changed

13 files changed

+48
-18
lines changed

.readthedocs.yml

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
version: 2
22

33
python:
4-
version: 3.7
4+
version: 3.8
55
install:
66
- requirements: docs/requirements.txt
77

classes/_registry.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55

66

77
def choose_registry( # noqa: WPS211
8-
# It has multiple argumnets, but I don't see an easy and performant way
8+
# It has multiple arguments, but I don't see an easy and performant way
99
# to refactor it: I don't want to create extra structures
1010
# and I don't want to create a class with methods.
1111
typ: type,
@@ -30,7 +30,7 @@ def choose_registry( # noqa: WPS211
3030
if is_concrete:
3131
# This means that this type has `__instancecheck__` defined,
3232
# which allows dynamic checks of what `isinstance` of this type.
33-
# That's why we also treat this type as a conrete.
33+
# That's why we also treat this type as a concrete.
3434
return concretes
3535
return instances
3636

classes/_typeclass.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -418,7 +418,7 @@ def __call__(
418418
And all typeclasses that match ``Callable[[int, int], int]`` signature
419419
will typecheck.
420420
"""
421-
# At first, we try all our conrete types,
421+
# At first, we try all our concrete types,
422422
# we don't cache it, because we cannot.
423423
# We only have runtime type info: `type([1]) == type(['a'])`.
424424
# It might be slow!

classes/contrib/mypy/typeops/call_signatures.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -43,7 +43,7 @@ def __init__(
4343
ctx: MethodSigContext,
4444
) -> None:
4545
"""Context that we need."""
46-
self._signature = signature
46+
self._signature = signature.copy_modified()
4747
self._instance_type = instance_type
4848
self._associated_type = associated_type
4949
self._ctx = ctx

tests/conftest.py

Lines changed: 5 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,16 @@
11
from contextlib import contextmanager
2+
from typing import Callable, ContextManager, Iterator
23

34
import pytest
45

6+
from classes._typeclass import _TypeClass # noqa: WPS450
7+
58

69
@pytest.fixture(scope='session')
7-
def clear_cache():
10+
def clear_cache() -> Callable[[_TypeClass], ContextManager]:
811
"""Fixture to clear typeclass'es cache before and after."""
912
@contextmanager
10-
def factory(typeclass):
13+
def factory(typeclass: _TypeClass) -> Iterator[None]:
1114
typeclass._dispatch_cache.clear() # noqa: WPS437
1215
yield
1316
typeclass._dispatch_cache.clear() # noqa: WPS437

tests/test_suppots.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class _ListOfStrMeta(type):
99
def __instancecheck__(cls, other) -> bool:
1010
return (
1111
isinstance(other, list) and
12-
len(other) and
12+
bool(other) and
1313
all(isinstance(list_item, str) for list_item in other)
1414
)
1515

@@ -48,7 +48,7 @@ def _my_len_list_str(instance: List[str]) -> int:
4848
(1, False), # default impl
4949
(_MyList(), True), # mro fallback
5050
(_ListOfStr(), True), # mro fallback
51-
(_ListOfStr([1, 2, 3]), True), # mro fallback
51+
(_ListOfStr(['a']), True), # mro fallback
5252
])
5353
def test_supports(data_type, expected: bool, clear_cache) -> None:
5454
"""Ensures that ``.supports`` works correctly."""

tests/test_typeclass/test_cache.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -34,7 +34,7 @@ def _my_abc(instance: _MyABC) -> int:
3434
return instance.get_number()
3535

3636

37-
def test_cache_concrete(clear_cache): # noqa: WPS218
37+
def test_cache_concrete(clear_cache) -> None: # noqa: WPS218
3838
"""Ensures that cache invalidation for ABC types work correctly."""
3939
with clear_cache(my_typeclass):
4040
assert not my_typeclass._dispatch_cache # noqa: WPS437
@@ -50,7 +50,7 @@ def test_cache_concrete(clear_cache): # noqa: WPS218
5050
assert not my_typeclass._dispatch_cache # noqa: WPS437
5151

5252

53-
def test_cached_calls(clear_cache):
53+
def test_cached_calls(clear_cache) -> None:
5454
"""Ensures that regular types trigger cache."""
5555
with clear_cache(my_typeclass):
5656
my_typeclass.instance(int)(_my_int)

tests/test_typeclass/test_call.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@ class _ListOfStrMeta(type):
99
def __instancecheck__(cls, other) -> bool:
1010
return (
1111
isinstance(other, list) and
12-
len(other) and
12+
bool(other) and
1313
all(isinstance(list_item, str) for list_item in other)
1414
)
1515

@@ -47,7 +47,7 @@ def _my_len_object(instance: object) -> int:
4747
@pytest.mark.parametrize('check_supports', [True, False])
4848
@pytest.mark.parametrize('clear_supports_cache', [True, False])
4949
@pytest.mark.parametrize(('data_type', 'expected'), [
50-
(['a', 'b'], 0), # conrete type
50+
(['a', 'b'], 0), # concrete type
5151
([], 1), # direct list call
5252
([1, 2, 3], 1), # direct list call
5353
('', 2), # sized protocol

tests/test_typeclass/test_callback.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -20,7 +20,7 @@ def _callback(
2020
return callback(instance)
2121

2222

23-
def test_callback():
23+
def test_callback() -> None:
2424
"""Tests that callback works."""
2525
assert _callback('a', example) == 1
2626
assert _callback('abcd', example) == 4

tests/test_typeclass/test_protocols.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -23,12 +23,12 @@ def __len__(self) -> int:
2323
return 2
2424

2525

26-
def test_sized_protocol():
26+
def test_sized_protocol() -> None:
2727
"""Ensure that sized protocol works."""
2828
assert protocols(_CustomSized(), '1') == '21'
2929
assert protocols([1, 2, 3], '0') == '30'
3030

3131

32-
def test_type_takes_over():
32+
def test_type_takes_over() -> None:
3333
"""Ensure that int protocol works."""
3434
assert protocols('a', 'b') == 'ab'

tests/test_typeclass/test_regular_types.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,7 @@ def _example_int(instance: int) -> str:
1818
return 'a' * instance
1919

2020

21-
def test_regular_type():
21+
def test_regular_type() -> None:
2222
"""Ensures that types correctly work."""
2323
assert example([1, 2, 3]) == '123'
2424
assert example(['a', 'b', 'c']) == 'abc'

tests/test_typeclass/test_repr.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -15,7 +15,7 @@ def my_typeclass(instance) -> str:
1515
"""Docs."""
1616

1717

18-
def test_str():
18+
def test_str() -> None:
1919
"""Ensures that ``str`` is correct."""
2020
assert str(my_typeclass) == '<typeclass "my_typeclass">'
2121
assert str(

typesafety/test_typeclass/test_generics/test_generics_regular.yml

Lines changed: 27 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -272,3 +272,30 @@
272272
...
273273
out: |
274274
main:10: error: Expected variadic tuple "Tuple[X`-1, ...]", got "Tuple[X`-1, X`-1]"
275+
276+
277+
- case: typeclass_regression259_mutated_signature
278+
disable_cache: false
279+
main: |
280+
from abc import ABCMeta, abstractmethod
281+
from classes import typeclass
282+
283+
@typeclass
284+
def my_typeclass(instance) -> int:
285+
...
286+
287+
class _MyABC(object, metaclass=ABCMeta):
288+
...
289+
290+
class _MyConcrete(_MyABC):
291+
...
292+
293+
@my_typeclass.instance(_MyABC)
294+
def _my_abc(instance: _MyABC) -> int:
295+
...
296+
297+
my_typeclass(_MyConcrete())
298+
299+
@my_typeclass.instance(int)
300+
def _my_int(instance: int) -> int:
301+
...

0 commit comments

Comments
 (0)