9
9
import sys
10
10
import time
11
11
from functools import partial
12
+ from typing import Any
12
13
from typing import Callable
13
14
from typing import Dict
14
15
from typing import List
24
25
25
26
import pytest
26
27
from _pytest import nodes
28
+ from _pytest .config import Config
27
29
from _pytest .main import ExitCode
30
+ from _pytest .main import Session
31
+ from _pytest .reports import CollectReport
32
+ from _pytest .reports import TestReport
28
33
29
34
REPORT_COLLECTING_RESOLUTION = 0.5
30
35
@@ -148,7 +153,7 @@ def pytest_addoption(parser):
148
153
)
149
154
150
155
151
- def pytest_configure (config ) :
156
+ def pytest_configure (config : Config ) -> None :
152
157
reporter = TerminalReporter (config , sys .stdout )
153
158
config .pluginmanager .register (reporter , "terminalreporter" )
154
159
if config .option .debug or config .option .traceconfig :
@@ -160,7 +165,7 @@ def mywriter(tags, args):
160
165
config .trace .root .setprocessor ("pytest:config" , mywriter )
161
166
162
167
163
- def getreportopt (config ) :
168
+ def getreportopt (config : Config ) -> str :
164
169
reportopts = ""
165
170
reportchars = config .option .reportchars
166
171
if not config .option .disable_warnings and "w" not in reportchars :
@@ -179,7 +184,7 @@ def getreportopt(config):
179
184
180
185
181
186
@pytest .hookimpl (trylast = True ) # after _pytest.runner
182
- def pytest_report_teststatus (report ) :
187
+ def pytest_report_teststatus (report : TestReport ) -> Tuple [ str , str , str ] :
183
188
if report .passed :
184
189
letter = "."
185
190
elif report .skipped :
@@ -233,29 +238,30 @@ def get_location(self, config):
233
238
234
239
235
240
class TerminalReporter :
236
- def __init__ (self , config , file = None ):
241
+ def __init__ (self , config : Config , file = None ):
237
242
import _pytest .config
238
243
239
244
self .config = config
240
245
self ._numcollected = 0
241
- self ._session = None
246
+ self ._session = None # type: Optional[Session]
242
247
self ._showfspath = None
243
248
244
- self .stats = {}
249
+ # XXX: needs TypedDict? warnings => WarningReport, others => BaseReport
250
+ self .stats = {} # type: Dict[str, List[Any]]
245
251
self .startdir = config .invocation_dir
246
252
if file is None :
247
253
file = sys .stdout
248
254
self ._tw = _pytest .config .create_terminal_writer (config , file )
249
255
# self.writer will be deprecated in pytest-3.4
250
256
self .writer = self ._tw
251
257
self ._screen_width = self ._tw .fullwidth
252
- self .currentfspath = None
258
+ self .currentfspath = None # type: Optional[int]
253
259
self .reportchars = getreportopt (config )
254
260
self .hasmarkup = self ._tw .hasmarkup
255
261
self .isatty = file .isatty ()
256
262
self ._progress_nodeids_reported = set () # type: Set[str]
257
263
self ._show_progress_info = self ._determine_show_progress_info ()
258
- self ._collect_report_last_write = None
264
+ self ._collect_report_last_write = None # type: Optional[float]
259
265
260
266
def _determine_show_progress_info (self ):
261
267
"""Return True if we should display progress information based on the current config"""
@@ -400,7 +406,7 @@ def pytest_runtest_logstart(self, nodeid, location):
400
406
fsid = nodeid .split ("::" )[0 ]
401
407
self .write_fspath_result (fsid , "" )
402
408
403
- def pytest_runtest_logreport (self , report ) :
409
+ def pytest_runtest_logreport (self , report : TestReport ) -> None :
404
410
self ._tests_ran = True
405
411
rep = report
406
412
res = self .config .hook .pytest_report_teststatus (report = rep , config = self .config )
@@ -440,7 +446,7 @@ def pytest_runtest_logreport(self, report):
440
446
self ._write_progress_information_filling_space ()
441
447
else :
442
448
self .ensure_newline ()
443
- self ._tw .write ("[%s]" % rep .node .gateway .id )
449
+ self ._tw .write ("[%s]" % rep .node .gateway .id ) # type: ignore
444
450
if self ._show_progress_info :
445
451
self ._tw .write (
446
452
self ._get_progress_information_message () + " " , cyan = True
@@ -452,6 +458,7 @@ def pytest_runtest_logreport(self, report):
452
458
self .currentfspath = - 2
453
459
454
460
def pytest_runtest_logfinish (self , nodeid ):
461
+ assert self ._session
455
462
if self .verbosity <= 0 and self ._show_progress_info :
456
463
if self ._show_progress_info == "count" :
457
464
num_tests = self ._session .testscollected
@@ -474,7 +481,8 @@ def pytest_runtest_logfinish(self, nodeid):
474
481
msg = self ._get_progress_information_message ()
475
482
self ._tw .write (msg + "\n " , ** {main_color : True })
476
483
477
- def _get_progress_information_message (self ):
484
+ def _get_progress_information_message (self ) -> str :
485
+ assert self ._session
478
486
collected = self ._session .testscollected
479
487
if self ._show_progress_info == "count" :
480
488
if collected :
@@ -485,8 +493,9 @@ def _get_progress_information_message(self):
485
493
return " [ {} / {} ]" .format (collected , collected )
486
494
else :
487
495
if collected :
488
- progress = len (self ._progress_nodeids_reported ) * 100 // collected
489
- return " [{:3d}%]" .format (progress )
496
+ return " [{:3d}%]" .format (
497
+ len (self ._progress_nodeids_reported ) * 100 // collected
498
+ )
490
499
return " [100%]"
491
500
492
501
def _write_progress_information_filling_space (self , color = None ):
@@ -514,7 +523,7 @@ def pytest_collection(self):
514
523
elif self .config .option .verbose >= 1 :
515
524
self .write ("collecting ... " , bold = True )
516
525
517
- def pytest_collectreport (self , report ):
526
+ def pytest_collectreport (self , report : CollectReport ):
518
527
if report .failed :
519
528
self .stats .setdefault ("error" , []).append (report )
520
529
elif report .skipped :
@@ -565,17 +574,18 @@ def report_collect(self, final=False):
565
574
self .write_line (line )
566
575
567
576
@pytest .hookimpl (trylast = True )
568
- def pytest_sessionstart (self , session ) :
577
+ def pytest_sessionstart (self , session : Session ) -> None :
569
578
self ._session = session
570
579
self ._sessionstarttime = time .time ()
571
580
if not self .showheader :
572
581
return
573
582
self .write_sep ("=" , "test session starts" , bold = True )
574
583
verinfo = platform .python_version ()
575
584
msg = "platform {} -- Python {}" .format (sys .platform , verinfo )
576
- if hasattr (sys , "pypy_version_info" ):
577
- verinfo = "." .join (map (str , sys .pypy_version_info [:3 ]))
578
- msg += "[pypy-{}-{}]" .format (verinfo , sys .pypy_version_info [3 ])
585
+ pypy_version_info = getattr (sys , "pypy_version_info" )
586
+ if pypy_version_info :
587
+ verinfo = "." .join (map (str , pypy_version_info [:3 ]))
588
+ msg += "[pypy-{}-{}]" .format (verinfo , pypy_version_info [3 ])
579
589
msg += ", pytest-{}, py-{}, pluggy-{}" .format (
580
590
pytest .__version__ , py .__version__ , pluggy .__version__
581
591
)
@@ -625,9 +635,10 @@ def pytest_collection_finish(self, session):
625
635
self ._write_report_lines_from_hooks (lines )
626
636
627
637
if self .config .getoption ("collectonly" ):
628
- if self .stats .get ("failed" ):
638
+ failed = self .stats .get ("failed" )
639
+ if failed :
629
640
self ._tw .sep ("!" , "collection failures" )
630
- for rep in self . stats . get ( " failed" ) :
641
+ for rep in failed :
631
642
rep .toterminal (self ._tw )
632
643
633
644
def _printcollecteditems (self , items ):
@@ -767,6 +778,7 @@ def getreports(self, name):
767
778
768
779
def summary_warnings (self ):
769
780
if self .hasopt ("w" ):
781
+ # XXX: this needs to be fixed
770
782
all_warnings = self .stats .get (
771
783
"warnings"
772
784
) # type: Optional[List[WarningReport]]
0 commit comments