@@ -2,36 +2,52 @@ import sys
2
2
import unittest .case
3
3
import unittest .result
4
4
import unittest .suite
5
- from _typeshed import Incomplete
5
+ from _typeshed import SupportsFlush , SupportsWrite
6
6
from collections .abc import Callable , Iterable
7
- from typing import TextIO
8
- from typing_extensions import TypeAlias
7
+ from typing import Any , Generic , Protocol , TypeVar
8
+ from typing_extensions import Never , TypeAlias
9
9
10
- _ResultClassType : TypeAlias = Callable [[TextIO , bool , int ], unittest . result . TestResult ]
10
+ _ResultClassType : TypeAlias = Callable [[_TextTestStream , bool , int ], TextTestResult ]
11
11
12
- class TextTestResult (unittest .result .TestResult ):
12
+ class _SupportsWriteAndFlush (SupportsWrite [str ], SupportsFlush , Protocol ): ...
13
+
14
+ # All methods used by unittest.runner.TextTestResult's stream
15
+ class _TextTestStream (_SupportsWriteAndFlush , Protocol ):
16
+ def writeln (self , arg : str | None = None ) -> str : ...
17
+
18
+ # _WritelnDecorator should have all the same attrs as its stream param.
19
+ # But that's not feasible to do Generically
20
+ # We can expand the attributes if requested
21
+ class _WritelnDecorator (_TextTestStream ):
22
+ def __init__ (self , stream : _TextTestStream ) -> None : ...
23
+ def __getattr__ (self , attr : str ) -> Any : ... # Any attribute from the stream type passed to __init__
24
+ # These attributes are prevented by __getattr__
25
+ stream : Never
26
+ __getstate__ : Never
27
+
28
+ _StreamT = TypeVar ("_StreamT" , bound = _TextTestStream , default = _WritelnDecorator )
29
+
30
+ class TextTestResult (unittest .result .TestResult , Generic [_StreamT ]):
13
31
descriptions : bool # undocumented
14
32
dots : bool # undocumented
15
33
separator1 : str
16
34
separator2 : str
17
35
showAll : bool # undocumented
18
- stream : TextIO # undocumented
36
+ stream : _StreamT # undocumented
19
37
if sys .version_info >= (3 , 12 ):
20
38
durations : unittest .result ._DurationsType | None
21
39
def __init__ (
22
- self , stream : TextIO , descriptions : bool , verbosity : int , * , durations : unittest .result ._DurationsType | None = None
40
+ self , stream : _StreamT , descriptions : bool , verbosity : int , * , durations : unittest .result ._DurationsType | None = None
23
41
) -> None : ...
24
42
else :
25
- def __init__ (self , stream : TextIO , descriptions : bool , verbosity : int ) -> None : ...
43
+ def __init__ (self , stream : _StreamT , descriptions : bool , verbosity : int ) -> None : ...
26
44
27
45
def getDescription (self , test : unittest .case .TestCase ) -> str : ...
28
46
def printErrorList (self , flavour : str , errors : Iterable [tuple [unittest .case .TestCase , str ]]) -> None : ...
29
47
30
48
class TextTestRunner :
31
49
resultclass : _ResultClassType
32
- # TODO: add `_WritelnDecorator` type
33
- # stream: _WritelnDecorator
34
- stream : Incomplete
50
+ stream : _WritelnDecorator
35
51
descriptions : bool
36
52
verbosity : int
37
53
failfast : bool
@@ -43,7 +59,7 @@ class TextTestRunner:
43
59
durations : unittest .result ._DurationsType | None
44
60
def __init__ (
45
61
self ,
46
- stream : TextIO | None = None ,
62
+ stream : _SupportsWriteAndFlush | None = None ,
47
63
descriptions : bool = True ,
48
64
verbosity : int = 1 ,
49
65
failfast : bool = False ,
@@ -57,7 +73,7 @@ class TextTestRunner:
57
73
else :
58
74
def __init__ (
59
75
self ,
60
- stream : TextIO | None = None ,
76
+ stream : _SupportsWriteAndFlush | None = None ,
61
77
descriptions : bool = True ,
62
78
verbosity : int = 1 ,
63
79
failfast : bool = False ,
@@ -68,5 +84,5 @@ class TextTestRunner:
68
84
tb_locals : bool = False ,
69
85
) -> None : ...
70
86
71
- def _makeResult (self ) -> unittest . result . TestResult : ...
72
- def run (self , test : unittest .suite .TestSuite | unittest .case .TestCase ) -> unittest . result . TestResult : ...
87
+ def _makeResult (self ) -> TextTestResult : ...
88
+ def run (self , test : unittest .suite .TestSuite | unittest .case .TestCase ) -> TextTestResult : ...
0 commit comments