1- import pkg_resources
21import re
32import time
43import warnings
54
5+ import pkg_resources
66import pytest
7-
8- from _pytest .runner import runtestprotocol
97from _pytest .resultlog import ResultLog
8+ from _pytest .runner import runtestprotocol
9+
10+ PYTEST_GTE_54 = pkg_resources .parse_version (
11+ pytest .__version__
12+ ) >= pkg_resources .parse_version ("5.4" )
1013
11- PYTEST_GTE_54 = pkg_resources .parse_version (pytest .__version__ ) >= pkg_resources .parse_version ("5.4" )
1214
1315def works_with_current_xdist ():
1416 """Returns compatibility with installed pytest-xdist version.
@@ -20,63 +22,70 @@ def works_with_current_xdist():
2022
2123 """
2224 try :
23- d = pkg_resources .get_distribution (' pytest-xdist' )
24- return d .parsed_version >= pkg_resources .parse_version (' 1.20' )
25+ d = pkg_resources .get_distribution (" pytest-xdist" )
26+ return d .parsed_version >= pkg_resources .parse_version (" 1.20" )
2527 except pkg_resources .DistributionNotFound :
2628 return None
2729
2830
2931# command line options
3032def pytest_addoption (parser ):
3133 group = parser .getgroup (
32- "rerunfailures" ,
33- "re-run failing tests to eliminate flaky failures" )
34+ "rerunfailures" , "re-run failing tests to eliminate flaky failures"
35+ )
3436 group ._addoption (
35- ' --only-rerun' ,
36- action = ' append' ,
37- dest = ' only_rerun' ,
37+ " --only-rerun" ,
38+ action = " append" ,
39+ dest = " only_rerun" ,
3840 type = str ,
3941 default = None ,
40- help = 'If passed, only rerun errors matching the regex provided. Pass this flag multiple times to accumulate a list of regexes to match'
42+ help = "If passed, only rerun errors matching the regex provided. "
43+ "Pass this flag multiple times to accumulate a list of regexes "
44+ "to match" ,
4145 )
4246 group ._addoption (
43- ' --reruns' ,
47+ " --reruns" ,
4448 action = "store" ,
4549 dest = "reruns" ,
4650 type = int ,
4751 default = 0 ,
48- help = "number of times to re-run failed tests. defaults to 0." )
52+ help = "number of times to re-run failed tests. defaults to 0." ,
53+ )
4954 group ._addoption (
50- ' --reruns-delay' ,
51- action = ' store' ,
52- dest = ' reruns_delay' ,
55+ " --reruns-delay" ,
56+ action = " store" ,
57+ dest = " reruns_delay" ,
5358 type = float ,
5459 default = 0 ,
55- help = ' add time (seconds) delay between reruns.'
60+ help = " add time (seconds) delay between reruns." ,
5661 )
5762
5863
5964def pytest_configure (config ):
6065 # add flaky marker
6166 config .addinivalue_line (
62- "markers" , "flaky(reruns=1, reruns_delay=0): mark test to re-run up "
63- "to 'reruns' times. Add a delay of 'reruns_delay' seconds "
64- "between re-runs." )
67+ "markers" ,
68+ "flaky(reruns=1, reruns_delay=0): mark test to re-run up "
69+ "to 'reruns' times. Add a delay of 'reruns_delay' seconds "
70+ "between re-runs." ,
71+ )
6572
6673
6774def _get_resultlog (config ):
6875 if PYTEST_GTE_54 :
6976 # hack
7077 from _pytest .resultlog import resultlog_key
78+
7179 return config ._store .get (resultlog_key , default = None )
7280 else :
73- return getattr (config , ' _resultlog' , None )
81+ return getattr (config , " _resultlog" , None )
7482
7583
7684def _set_resultlog (config , resultlog ):
7785 if PYTEST_GTE_54 :
7886 # hack
7987 from _pytest .resultlog import resultlog_key
88+
8089 config ._store [resultlog_key ] = resultlog
8190 else :
8291 config ._resultlog = resultlog
@@ -88,10 +97,9 @@ def check_options(config):
8897 val = config .getvalue
8998 if not val ("collectonly" ):
9099 if config .option .reruns != 0 :
91- if config .option .usepdb : # a core option
100+ if config .option .usepdb : # a core option
92101 raise pytest .UsageError ("--reruns incompatible with --pdb" )
93102
94-
95103 resultlog = _get_resultlog (config )
96104 if resultlog :
97105 logfile = resultlog .logfile
@@ -146,8 +154,9 @@ def get_reruns_delay(item):
146154
147155 if delay < 0 :
148156 delay = 0
149- warnings .warn ('Delay time between re-runs cannot be < 0. '
150- 'Using default value: 0' )
157+ warnings .warn (
158+ "Delay time between re-runs cannot be < 0. Using default value: 0"
159+ )
151160
152161 return delay
153162
@@ -156,9 +165,9 @@ def _remove_cached_results_from_failed_fixtures(item):
156165 """
157166 Note: remove all cached_result attribute from every fixture
158167 """
159- cached_result = ' cached_result'
160- fixture_info = getattr (item , ' _fixtureinfo' , None )
161- for fixture_def_str in getattr (fixture_info , ' name2fixturedefs' , ()):
168+ cached_result = " cached_result"
169+ fixture_info = getattr (item , " _fixtureinfo" , None )
170+ for fixture_def_str in getattr (fixture_info , " name2fixturedefs" , ()):
162171 fixture_defs = fixture_info .name2fixturedefs [fixture_def_str ]
163172 for fixture_def in fixture_defs :
164173 if getattr (fixture_def , cached_result , None ) is not None :
@@ -172,18 +181,19 @@ def _remove_cached_results_from_failed_fixtures(item):
172181
173182def _remove_failed_setup_state_from_session (item ):
174183 """
175- Note: remove all _prepare_exc attribute from every col in stack of _setupstate and cleaning the stack itself
184+ Note: remove all _prepare_exc attribute from every col in stack of
185+ _setupstate and cleaning the stack itself
176186 """
177187 prepare_exc = "_prepare_exc"
178- setup_state = getattr (item .session , ' _setupstate' )
188+ setup_state = getattr (item .session , " _setupstate" )
179189 for col in setup_state .stack :
180190 if hasattr (col , prepare_exc ):
181191 delattr (col , prepare_exc )
182192 setup_state .stack = list ()
183193
184194
185195def _should_hard_fail_on_error (session_config , report ):
186- if report .outcome != ' failed' :
196+ if report .outcome != " failed" :
187197 return False
188198
189199 rerun_errors = session_config .option .only_rerun
@@ -213,26 +223,30 @@ def pytest_runtest_protocol(item, nextitem):
213223 # first item if necessary
214224 check_options (item .session .config )
215225 delay = get_reruns_delay (item )
216- parallel = hasattr (item .config , ' slaveinput' )
226+ parallel = hasattr (item .config , " slaveinput" )
217227 item .execution_count = 0
218228
219229 need_to_run = True
220230 while need_to_run :
221231 item .execution_count += 1
222- item .ihook .pytest_runtest_logstart (nodeid = item .nodeid ,
223- location = item .location )
232+ item .ihook .pytest_runtest_logstart (nodeid = item .nodeid , location = item .location )
224233 reports = runtestprotocol (item , nextitem = nextitem , log = False )
225234
226235 for report in reports : # 3 reports: setup, call, teardown
227236 is_terminal_error = _should_hard_fail_on_error (item .session .config , report )
228237 report .rerun = item .execution_count - 1
229- xfail = hasattr (report , 'wasxfail' )
230- if item .execution_count > reruns or not report .failed or xfail or is_terminal_error :
238+ xfail = hasattr (report , "wasxfail" )
239+ if (
240+ item .execution_count > reruns
241+ or not report .failed
242+ or xfail
243+ or is_terminal_error
244+ ):
231245 # last run or no failure detected, log normally
232246 item .ihook .pytest_runtest_logreport (report = report )
233247 else :
234248 # failure detected and reruns not exhausted, since i < reruns
235- report .outcome = ' rerun'
249+ report .outcome = " rerun"
236250 time .sleep (delay )
237251
238252 if not parallel or works_with_current_xdist ():
@@ -247,17 +261,16 @@ def pytest_runtest_protocol(item, nextitem):
247261 else :
248262 need_to_run = False
249263
250- item .ihook .pytest_runtest_logfinish (nodeid = item .nodeid ,
251- location = item .location )
264+ item .ihook .pytest_runtest_logfinish (nodeid = item .nodeid , location = item .location )
252265
253266 return True
254267
255268
256269def pytest_report_teststatus (report ):
257270 """Adapted from https://pytest.org/latest/_modules/_pytest/skipping.html
258271 """
259- if report .outcome == ' rerun' :
260- return ' rerun' , 'R' , (' RERUN' , {' yellow' : True })
272+ if report .outcome == " rerun" :
273+ return " rerun" , "R" , (" RERUN" , {" yellow" : True })
261274
262275
263276def pytest_terminal_summary (terminalreporter ):
@@ -269,7 +282,7 @@ def pytest_terminal_summary(terminalreporter):
269282
270283 lines = []
271284 for char in tr .reportchars :
272- if char in 'rR' :
285+ if char in "rR" :
273286 show_rerun (terminalreporter , lines )
274287
275288 if lines :
@@ -283,7 +296,7 @@ def show_rerun(terminalreporter, lines):
283296 if rerun :
284297 for rep in rerun :
285298 pos = rep .nodeid
286- lines .append ("RERUN %s" % (pos , ))
299+ lines .append ("RERUN {}" . format (pos ))
287300
288301
289302class RerunResultLog (ResultLog ):
@@ -299,17 +312,17 @@ def pytest_runtest_logreport(self, report):
299312 return
300313 res = self .config .hook .pytest_report_teststatus (report = report )
301314 code = res [1 ]
302- if code == 'x' :
315+ if code == "x" :
303316 longrepr = str (report .longrepr )
304- elif code == 'X' :
305- longrepr = ''
317+ elif code == "X" :
318+ longrepr = ""
306319 elif report .passed :
307320 longrepr = ""
308321 elif report .failed :
309322 longrepr = str (report .longrepr )
310323 elif report .skipped :
311324 longrepr = str (report .longrepr [2 ])
312- elif report .outcome == ' rerun' :
325+ elif report .outcome == " rerun" :
313326 longrepr = str (report .longrepr )
314327 else :
315328 longrepr = str (report .longrepr )
0 commit comments