Skip to content

Commit d3536ae

Browse files
committed
Work with xdist 2.0
Fixes #411, at cost of support for xdist 1.22 and earlier from 2017.
1 parent 694f7fd commit d3536ae

File tree

6 files changed

+17
-33
lines changed

6 files changed

+17
-33
lines changed

AUTHORS.rst

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -38,3 +38,4 @@ Authors
3838
* Hugo van Kemenade - https://github.com/hugovk
3939
* Michael Manganiello - https://github.com/adamantike
4040
* Anders Hovmöller - https://github.com/boxed
41+
* Zac Hatfield-Dodds - https://zhd.dev

CHANGELOG.rst

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,12 @@
11
Changelog
22
=========
33

4+
2.10.1 (2020-06-??)
5+
-------------------
6+
7+
* Support for ``pytest-xdist`` 2.0, which breaks compatibility with ``pytest-xdist`` before 1.22.3 (from 2017).
8+
Contributed by Zac Hatfield-Dodds in `#412 <https://github.com/pytest-dev/pytest-cov/pull/412>`_.
9+
410
2.10.0 (2020-06-12)
511
-------------------
612

src/pytest_cov/compat.py

Lines changed: 0 additions & 19 deletions
Original file line numberDiff line numberDiff line change
@@ -29,22 +29,3 @@ def testsfailed(self):
2929
@testsfailed.setter
3030
def testsfailed(self, value):
3131
setattr(self._session, self._attr, value)
32-
33-
34-
def _attrgetter(attr):
35-
"""
36-
Return a callable object that fetches attr from its operand.
37-
38-
Unlike operator.attrgetter, the returned callable supports an extra two
39-
arg form for a default.
40-
"""
41-
def fn(obj, *args):
42-
return getattr(obj, attr, *args)
43-
44-
return fn
45-
46-
47-
worker = 'slave' # for compatability with pytest-xdist<=1.22.0
48-
workerid = worker + 'id'
49-
workerinput = _attrgetter(worker + 'input')
50-
workeroutput = _attrgetter(worker + 'output')

src/pytest_cov/engine.py

Lines changed: 7 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -11,8 +11,6 @@
1111
from coverage.data import CoverageData
1212

1313
from .compat import StringIO
14-
from .compat import workerinput
15-
from .compat import workeroutput
1614
from .embed import cleanup
1715

1816

@@ -271,7 +269,7 @@ def start(self):
271269
def configure_node(self, node):
272270
"""Workers need to know if they are collocated and what files have moved."""
273271

274-
workerinput(node).update({
272+
node.workerinput.update({
275273
'cov_master_host': socket.gethostname(),
276274
'cov_master_topdir': self.topdir,
277275
'cov_master_rsync_roots': [str(root) for root in node.nodemanager.roots],
@@ -282,7 +280,7 @@ def testnodedown(self, node, error):
282280

283281
# If worker doesn't return any data then it is likely that this
284282
# plugin didn't get activated on the worker side.
285-
output = workeroutput(node, {})
283+
output = getattr(node, 'workeroutput', {})
286284
if 'cov_worker_node_id' not in output:
287285
self.failed_workers.append(node)
288286
return
@@ -341,12 +339,12 @@ def start(self):
341339
cleanup()
342340

343341
# Determine whether we are collocated with master.
344-
self.is_collocated = (socket.gethostname() == workerinput(self.config)['cov_master_host'] and
345-
self.topdir == workerinput(self.config)['cov_master_topdir'])
342+
self.is_collocated = (socket.gethostname() == self.config.workerinput['cov_master_host'] and
343+
self.topdir == self.config.workerinput['cov_master_topdir'])
346344

347345
# If we are not collocated then rewrite master paths to worker paths.
348346
if not self.is_collocated:
349-
master_topdir = workerinput(self.config)['cov_master_topdir']
347+
master_topdir = self.config.workerinput['cov_master_topdir']
350348
worker_topdir = self.topdir
351349
if self.cov_source is not None:
352350
self.cov_source = [source.replace(master_topdir, worker_topdir)
@@ -375,7 +373,7 @@ def finish(self):
375373

376374
# If we are collocated then just inform the master of our
377375
# data file to indicate that we have finished.
378-
workeroutput(self.config)['cov_worker_node_id'] = self.nodeid
376+
self.config.workeroutput['cov_worker_node_id'] = self.nodeid
379377
else:
380378
self.cov.combine()
381379
self.cov.save()
@@ -391,7 +389,7 @@ def finish(self):
391389
else:
392390
data = self.cov.get_data().dumps()
393391

394-
workeroutput(self.config).update({
392+
self.config.workeroutput.update({
395393
'cov_worker_path': self.topdir,
396394
'cov_worker_node_id': self.nodeid,
397395
'cov_worker_data': data,

src/pytest_cov/plugin.py

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -203,7 +203,7 @@ class Config(object):
203203
self.options.cov_fail_under = cov_config.fail_under
204204

205205
def _is_worker(self, session):
206-
return compat.workerinput(session.config, None) is not None
206+
return getattr(session.config, 'workerinput', None) is not None
207207

208208
def pytest_sessionstart(self, session):
209209
"""At session start determine our implementation and delegate to it."""
@@ -220,8 +220,7 @@ def pytest_sessionstart(self, session):
220220
self.pid = os.getpid()
221221
if self._is_worker(session):
222222
nodeid = (
223-
compat.workerinput(session.config)
224-
.get(compat.workerid, getattr(session, 'nodeid'))
223+
session.config.workerinput.get('workerid', getattr(session, 'nodeid'))
225224
)
226225
self.start(engine.DistWorker, session.config, nodeid)
227226
elif not self._started:

tests/test_pytest_cov.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
1919
from six import exec_
2020

2121
import pytest_cov.plugin
22-
from pytest_cov import compat
2322

2423
try:
2524
from StringIO import StringIO
@@ -28,7 +27,7 @@
2827

2928
coverage, platform # required for skipif mark on test_cov_min_from_coveragerc
3029

31-
max_worker_restart_0 = "--max-" + compat.worker + "-restart=0"
30+
max_worker_restart_0 = "--max-worker-restart=0"
3231

3332
SCRIPT = '''
3433
import sys, helper

0 commit comments

Comments
 (0)