1- # -*- coding: utf-8 -*-
2-
31from typing import Callable , Dict , Generic , NoReturn , Type , TypeVar , overload
42
53from typing_extensions import Literal
@@ -24,21 +22,21 @@ class _TypeClass(Generic[_TypeClassType, _ReturnType, _CallbackType]):
2422 >>> @typeclass
2523 ... def used(instance, other: int) -> int:
2624 ... '''Example typeclass to be used later.'''
27- ...
25+
2826 >>> @used.instance(int)
2927 ... def _used_int(instance: int, other: int) -> int:
3028 ... return instance + other
31- ...
29+
3230 >>> def accepts_typeclass(
3331 ... callback: Callable[[int, int], int],
3432 ... ) -> int:
3533 ... return callback(1, 3)
36- ...
37- >>> accepts_typeclass(used)
38- 4
34+
35+ >>> assert accepts_typeclass(used) == 4
3936
4037 Take a note, that we structural subtyping here.
41- And all typeclasses that match this signature will typecheck.
38+ And all typeclasses that match ``Callable[[int, int], int]`` signature
39+ will typecheck.
4240
4341 """
4442
@@ -123,8 +121,8 @@ def instance(
123121 ) -> Callable [
124122 [Callable [[_InstanceType ], _ReturnType ]],
125123 NoReturn , # We need this type to disallow direct instance calls
126- ]: # pragma: no cover
127- ...
124+ ]:
125+ """Case for regular typeclasses."""
128126
129127 @overload
130128 def instance (
@@ -135,8 +133,8 @@ def instance(
135133 ) -> Callable [
136134 [Callable [[_InstanceType ], _ReturnType ]],
137135 NoReturn , # We need this type to disallow direct instance calls
138- ]: # pragma: no cover
139- ...
136+ ]:
137+ """Case for protocol based typeclasses."""
140138
141139 def instance (
142140 self ,
@@ -182,7 +180,7 @@ def typeclass(
182180 >>> @typeclass
183181 ... def example(instance) -> str:
184182 ... '''Example typeclass.'''
185- ...
183+
186184 >>> example(1)
187185 Traceback (most recent call last):
188186 ...
@@ -202,9 +200,8 @@ def typeclass(
202200 >>> @example.instance(int)
203201 ... def _example_int(instance: int) -> str:
204202 ... return 'int case'
205- ...
206- >>> example(1)
207- 'int case'
203+
204+ >>> assert example(1) == 'int case'
208205
209206 Now we have a specific instance for ``int``
210207 which does something different from the default implementation.
@@ -227,9 +224,8 @@ def typeclass(
227224 >>> @example.instance(str)
228225 ... def _example_str(instance: str) -> str:
229226 ... return instance
230- ...
231- >>> example('a')
232- 'a'
227+
228+ >>> assert example('a') == 'a'
233229
234230 Now it works with ``str`` as well. But differently.
235231 This allows developer to base the implementation on type information.
@@ -252,7 +248,6 @@ def typeclass(
252248 >>> class MyGeneric(Generic[T]):
253249 ... def __init__(self, arg: T) -> None:
254250 ... self.arg = arg
255- ...
256251
257252 Now, let's define the typeclass instance for this type:
258253
@@ -261,17 +256,15 @@ def typeclass(
261256 >>> @example.instance(MyGeneric)
262257 ... def _my_generic_example(instance: MyGeneric) -> str:
263258 ... return 'generi' + str(instance.arg)
264- ...
265- >>> example(MyGeneric('c'))
266- 'generic'
259+
260+ >>> assert example(MyGeneric('c')) == 'generic'
267261
268262 This case will work for all type parameters of ``MyGeneric``,
269263 or in other words it can be assumed as ``MyGeneric[Any]``:
270264
271265 .. code:: python
272266
273- >>> example(MyGeneric(1))
274- 'generi1'
267+ >>> assert example(MyGeneric(1)) == 'generi1'
275268
276269 In the future, when Python will have new type mechanisms,
277270 we would like to improve our support for specific generic instances
@@ -290,16 +283,14 @@ def typeclass(
290283 >>> @example.instance(Sequence, is_protocol=True)
291284 ... def _sequence_example(instance: Sequence) -> str:
292285 ... return ','.join(str(item) for item in instance)
293- ...
294- >>> example([1, 2, 3])
295- '1,2,3'
286+
287+ >>> assert example([1, 2, 3]) == '1,2,3'
296288
297289 But, ``str`` will still have higher priority over ``Sequence``:
298290
299291 .. code:: python
300292
301- >>> example('abc')
302- 'abc'
293+ >>> assert example('abc') == 'abc'
303294
304295 We also support user-defined protocols:
305296
@@ -308,21 +299,19 @@ def typeclass(
308299 >>> from typing_extensions import Protocol
309300 >>> class CustomProtocol(Protocol):
310301 ... field: str
311- ...
302+
312303 >>> @example.instance(CustomProtocol, is_protocol=True)
313304 ... def _custom_protocol_example(instance: CustomProtocol) -> str:
314305 ... return instance.field
315- ...
316306
317307 Now, let's build a class that match this protocol and test it:
318308
319309 .. code:: python
320310
321311 >>> class WithField(object):
322312 ... field: str = 'with field'
323- ...
324- >>> example(WithField())
325- 'with field'
313+
314+ >>> assert example(WithField()) == 'with field'
326315
327316 Remember, that generic protocols have the same limitation as generic types.
328317
0 commit comments