Skip to content

Commit 3649b09

Browse files
authored
Merge pull request #117 from gnikonorov/issue_80
Add in pre-commit to repo
2 parents be9f031 + 19ab6b7 commit 3649b09

9 files changed

Lines changed: 461 additions & 239 deletions

.pre-commit-config.yaml

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
repos:
2+
- repo: https://github.com/psf/black
3+
rev: 19.10b0
4+
hooks:
5+
- id: black
6+
args: [--safe, --quiet]
7+
- repo: https://github.com/pre-commit/pre-commit-hooks
8+
rev: v3.1.0
9+
hooks:
10+
- id: trailing-whitespace
11+
- id: end-of-file-fixer
12+
- id: fix-encoding-pragma
13+
args: [--remove]
14+
- id: check-yaml
15+
- id: debug-statements
16+
language_version: python3
17+
- repo: https://gitlab.com/pycqa/flake8
18+
rev: 3.8.3
19+
hooks:
20+
- id: flake8
21+
language_version: python3
22+
additional_dependencies: [flake8-typing-imports==1.9.0]
23+
- repo: https://github.com/asottile/reorder_python_imports
24+
rev: v2.3.2
25+
hooks:
26+
- id: reorder-python-imports
27+
args: ['--application-directories=.:src', --py3-plus]
28+
- repo: https://github.com/asottile/pyupgrade
29+
rev: v2.7.1
30+
hooks:
31+
- id: pyupgrade
32+
args: [--py3-plus]
33+
- repo: local
34+
hooks:
35+
- id: rst
36+
name: rst
37+
entry: rst-lint --encoding utf-8
38+
files: ^(CHANGES.rst|README.rst)$
39+
language: python
40+
additional_dependencies: [pygments, restructuredtext_lint]

.travis.yml

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -14,4 +14,8 @@ env:
1414
install:
1515
- pip install -q pytest==$PYTEST
1616
- pip install -q -e .
17-
script: py.test
17+
- pip install -q pre-commit
18+
- pre-commit install
19+
script:
20+
- if [[ "$TRAVIS_PYTHON_VERSION" > "3.5" ]] && [[ "$TRAVIS_PYTHON_VERSION" != pypy* ]]; then pre-commit run --all-files --show-diff-on-failure; fi
21+
- py.test

CHANGES.rst

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,16 @@ Changelog
55
----------------
66

77
- Drop dependency on ``mock``.
8+
89
- Add in new flag ``--only-rerun`` to allow for users to rerun only certain errors.
910

11+
- Add support for pre-commit and add a linting tox target.
12+
(`#117 <https://github.com/pytest-dev/pytest-rerunfailures/pull/117>`_)
13+
(PR from `@gnikonorov`_)
14+
15+
.. _@gnikonorov: https://github.com/gnikonorov
16+
17+
1018
9.0 (2020-03-18)
1119
----------------
1220

CONTRIBUTING.rst

Lines changed: 40 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,40 @@
1+
============================
2+
Contribution getting started
3+
============================
4+
5+
Contributions are highly welcomed and appreciated. Every little bit of help counts,
6+
so do not hesitate!
7+
8+
.. contents::
9+
:depth: 2
10+
:backlinks: none
11+
12+
13+
Preparing Pull Requests
14+
-----------------------
15+
16+
#. Fork the repository.
17+
18+
#. Enable and install `pre-commit <https://pre-commit.com>`_ to ensure style-guides and code checks are followed::
19+
20+
$ pip install --user pre-commit
21+
$ pre-commit install
22+
23+
Afterwards ``pre-commit`` will run whenever you commit.
24+
25+
Note that this is automatically done when running ``tox -e linting``.
26+
27+
https://pre-commit.com/ is a framework for managing and maintaining multi-language pre-commit hooks
28+
to ensure code-style and code formatting is consistent.
29+
30+
#. Install `tox <https://tox.readthedocs.io/en/latest/>`_::
31+
32+
Tox is used to run all the tests and will automatically setup virtualenvs
33+
to run the tests in. Implicitly http://www.virtualenv.org/en/latest/ is used::
34+
35+
$ pip install tox
36+
$ tox -e linting,py37
37+
38+
#. Follow **PEP-8** for naming and `black <https://github.com/psf/black>`_ for formatting.
39+
40+
#. Add a line item to the current **unreleased** version in ``CHANGES.rst``, unless the change is trivial.

README.rst

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -65,7 +65,7 @@ only rerun those errors that match ``AssertionError``:
6565
.. code-block:: bash
6666
6767
$ pytest --reruns 5 --only-rerun AssertionError
68-
68+
6969
Passing the flag multiple times accumulates the arguments, so the following would only rerun
7070
those errors that match ``AssertionError`` or ``ValueError``:
7171

pytest_rerunfailures.py

Lines changed: 61 additions & 48 deletions
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,16 @@
1-
import pkg_resources
21
import re
32
import time
43
import warnings
54

5+
import pkg_resources
66
import pytest
7-
8-
from _pytest.runner import runtestprotocol
97
from _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

1315
def 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
3032
def 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

5964
def 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

6774
def _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

7684
def _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

173182
def _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

185195
def _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

256269
def 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

263276
def 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

289302
class 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

Comments
 (0)