Hello community, here is the log from the commit of package python-pytest-xdist for openSUSE:Factory checked in at 2018-01-05 01:02:48 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Comparing /work/SRC/openSUSE:Factory/python-pytest-xdist (Old) and /work/SRC/openSUSE:Factory/.python-pytest-xdist.new (New) ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-pytest-xdist" Fri Jan 5 01:02:48 2018 rev:3 rq:561517 version:1.21.0 Changes: -------- --- /work/SRC/openSUSE:Factory/python-pytest-xdist/python-pytest-xdist.changes 2017-11-17 10:59:40.001463034 +0100 +++ /work/SRC/openSUSE:Factory/.python-pytest-xdist.new/python-pytest-xdist.changes 2018-01-05 01:04:47.544675722 +0100 @@ -1,0 +2,13 @@ +Wed Jan 3 23:12:36 UTC 2018 - a...@gmx.de + +- update to version 1.21.0: + * Deprecations and Removals + + Drop support for EOL Python 2.6. (#259) + * Features + + New --dist=loadfile option which load-distributes test to + workers grouped by the file the tests live in. (#242) + * Bug Fixes + + Fix accidental mutation of test report during serialization + causing longrepr string-ification to break. (#241) + +------------------------------------------------------------------- Old: ---- pytest-xdist-1.20.1.tar.gz New: ---- pytest-xdist-1.21.0.tar.gz ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ Other differences: ------------------ ++++++ python-pytest-xdist.spec ++++++ --- /var/tmp/diff_new_pack.oPgaN3/_old 2018-01-05 01:04:48.572333806 +0100 +++ /var/tmp/diff_new_pack.oPgaN3/_new 2018-01-05 01:04:48.576332476 +0100 @@ -1,7 +1,7 @@ # # spec file for package python-pytest-xdist # -# Copyright (c) 2017 SUSE LINUX GmbH, Nuernberg, Germany. +# Copyright (c) 2018 SUSE LINUX GmbH, Nuernberg, Germany. # # All modifications and additions to the file contributed by third parties # remain the property of their copyright owners, unless otherwise agreed @@ -18,7 +18,7 @@ %{?!python_module:%define python_module() python-%{**} python3-%{**}} Name: python-pytest-xdist -Version: 1.20.1 +Version: 1.21.0 Release: 0 Summary: Distributed testing and loop-on-failing for py.test License: MIT ++++++ pytest-xdist-1.20.1.tar.gz -> pytest-xdist-1.21.0.tar.gz ++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/.gitignore new/pytest-xdist-1.21.0/.gitignore --- old/pytest-xdist-1.20.1/.gitignore 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/.gitignore 2017-12-26 13:55:58.000000000 +0100 @@ -30,3 +30,4 @@ .tox/ .cache/ .eggs/ +.idea/ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/.travis.yml new/pytest-xdist-1.21.0/.travis.yml --- old/pytest-xdist-1.20.1/.travis.yml 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/.travis.yml 2017-12-26 13:55:58.000000000 +0100 @@ -12,7 +12,6 @@ - pytest-com...@python.org python: -- '2.6' - '2.7' - '3.4' - '3.5' @@ -21,6 +20,7 @@ - TOXENV=py-pytest30 - TOXENV=py-pytest31 - TOXENV=py-pytest32 +- TOXENV=py-pytest33 install: pip install tox setuptools_scm script: tox diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/CHANGELOG.rst new/pytest-xdist-1.21.0/CHANGELOG.rst --- old/pytest-xdist-1.20.1/CHANGELOG.rst 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/CHANGELOG.rst 2017-12-26 13:55:58.000000000 +0100 @@ -1,3 +1,29 @@ +pytest-xdist 1.21.0 (2017-12-22) +================================ + +Deprecations and Removals +------------------------- + +- Drop support for EOL Python 2.6. (`#259 + <https://github.com/pytest-dev/pytest-xdist/issues/259>`_) + + +Features +-------- + +- New ``--dist=loadfile`` option which load-distributes test to workers grouped + by the file the tests live in. (`#242 + <https://github.com/pytest-dev/pytest-xdist/issues/242>`_) + + +Bug Fixes +--------- + +- Fix accidental mutation of test report during serialization causing longrepr + string-ification to break. (`#241 + <https://github.com/pytest-dev/pytest-xdist/issues/241>`_) + + pytest-xdist 1.20.1 (2017-10-05) ================================ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/PKG-INFO new/pytest-xdist-1.21.0/PKG-INFO --- old/pytest-xdist-1.20.1/PKG-INFO 2017-10-05 22:18:54.000000000 +0200 +++ new/pytest-xdist-1.21.0/PKG-INFO 2017-12-26 13:56:21.000000000 +0100 @@ -1,6 +1,6 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: pytest-xdist -Version: 1.20.1 +Version: 1.21.0 Summary: py.test xdist plugin for distributed testing and loop-on-failing modes Home-page: https://github.com/pytest-dev/pytest-xdist Author: holger krekel and contributors @@ -10,15 +10,23 @@ Description: .. image:: http://img.shields.io/pypi/v/pytest-xdist.svg + :alt: PyPI version + :target: https://pypi.python.org/pypi/pytest-xdist + + .. image:: https://img.shields.io/pypi/pyversions/pytest-xdist.svg + :alt: Python versions :target: https://pypi.python.org/pypi/pytest-xdist .. image:: https://anaconda.org/conda-forge/pytest-xdist/badges/version.svg + :alt: Anaconda version :target: https://anaconda.org/conda-forge/pytest-xdist .. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master + :alt: Travis CI build status :target: https://travis-ci.org/pytest-dev/pytest-xdist .. image:: https://ci.appveyor.com/api/projects/status/56eq1a1avd4sdd7e/branch/master?svg=true + :alt: AppVeyor build status :target: https://ci.appveyor.com/project/pytestbot/pytest-xdist xdist: pytest distributed testing plugin @@ -238,7 +246,7 @@ .. code-block:: ini [pytest] - addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python2.6 + addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python3.6 and then just type:: @@ -322,6 +330,22 @@ Currently the groupings can't be customized, with grouping by class takes priority over grouping by module. + Sending tests to the same worker based on their file + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + + *New in version 1.21.* + + .. note:: + This is an **experimental** feature: the actual functionality will + likely stay the same, but the CLI might change slightly in future versions. + + You can send tests to the same worker grouped by their filename by using the + ``--dist=loadfile`` option, so tests of the same file are guaranteed to run + in the same worker. + + Using the example in the previous section, all tests from ``test_container.py`` will + run in the same worker, as well as the tests in ``test_io.py``. + Specifying "rsync" dirs in an ini-file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -356,4 +380,10 @@ Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Utilities Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/README.rst new/pytest-xdist-1.21.0/README.rst --- old/pytest-xdist-1.20.1/README.rst 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/README.rst 2017-12-26 13:55:58.000000000 +0100 @@ -1,15 +1,23 @@ .. image:: http://img.shields.io/pypi/v/pytest-xdist.svg + :alt: PyPI version + :target: https://pypi.python.org/pypi/pytest-xdist + +.. image:: https://img.shields.io/pypi/pyversions/pytest-xdist.svg + :alt: Python versions :target: https://pypi.python.org/pypi/pytest-xdist .. image:: https://anaconda.org/conda-forge/pytest-xdist/badges/version.svg + :alt: Anaconda version :target: https://anaconda.org/conda-forge/pytest-xdist .. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master + :alt: Travis CI build status :target: https://travis-ci.org/pytest-dev/pytest-xdist .. image:: https://ci.appveyor.com/api/projects/status/56eq1a1avd4sdd7e/branch/master?svg=true + :alt: AppVeyor build status :target: https://ci.appveyor.com/project/pytestbot/pytest-xdist xdist: pytest distributed testing plugin @@ -229,7 +237,7 @@ .. code-block:: ini [pytest] - addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python2.6 + addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python3.6 and then just type:: @@ -313,6 +321,22 @@ Currently the groupings can't be customized, with grouping by class takes priority over grouping by module. +Sending tests to the same worker based on their file +++++++++++++++++++++++++++++++++++++++++++++++++++++ + +*New in version 1.21.* + +.. note:: + This is an **experimental** feature: the actual functionality will + likely stay the same, but the CLI might change slightly in future versions. + +You can send tests to the same worker grouped by their filename by using the +``--dist=loadfile`` option, so tests of the same file are guaranteed to run +in the same worker. + +Using the example in the previous section, all tests from ``test_container.py`` will +run in the same worker, as well as the tests in ``test_io.py``. + Specifying "rsync" dirs in an ini-file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/appveyor.yml new/pytest-xdist-1.21.0/appveyor.yml --- old/pytest-xdist-1.20.1/appveyor.yml 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/appveyor.yml 2017-12-26 13:55:58.000000000 +0100 @@ -1,18 +1,17 @@ environment: matrix: # note: please use "tox --listenvs" to populate the build matrix - - TOXENV: "py26-pytest30" - - TOXENV: "py27-pytest30" - - TOXENV: "py34-pytest30" - - TOXENV: "py35-pytest30" - - TOXENV: "py36-pytest30" - - TOXENV: "py27-pytest30-pexpect" - - TOXENV: "py35-pytest30-pexpect" + - TOXENV: "py27-pytest33" + - TOXENV: "py34-pytest33" + - TOXENV: "py35-pytest33" + - TOXENV: "py36-pytest33" + - TOXENV: "py27-pytest33-pexpect" + - TOXENV: "py36-pytest33-pexpect" - TOXENV: "flakes" - TOXENV: "readme" install: - - C:\Python35\python -m pip install tox setuptools_scm + - C:\Python35\python -m pip install -U tox setuptools_scm pip build: false # Not a C# project, build stuff at the test step instead. diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/pytest_xdist.egg-info/PKG-INFO new/pytest-xdist-1.21.0/pytest_xdist.egg-info/PKG-INFO --- old/pytest-xdist-1.20.1/pytest_xdist.egg-info/PKG-INFO 2017-10-05 22:18:54.000000000 +0200 +++ new/pytest-xdist-1.21.0/pytest_xdist.egg-info/PKG-INFO 2017-12-26 13:56:21.000000000 +0100 @@ -1,6 +1,6 @@ -Metadata-Version: 1.1 +Metadata-Version: 1.2 Name: pytest-xdist -Version: 1.20.1 +Version: 1.21.0 Summary: py.test xdist plugin for distributed testing and loop-on-failing modes Home-page: https://github.com/pytest-dev/pytest-xdist Author: holger krekel and contributors @@ -10,15 +10,23 @@ Description: .. image:: http://img.shields.io/pypi/v/pytest-xdist.svg + :alt: PyPI version + :target: https://pypi.python.org/pypi/pytest-xdist + + .. image:: https://img.shields.io/pypi/pyversions/pytest-xdist.svg + :alt: Python versions :target: https://pypi.python.org/pypi/pytest-xdist .. image:: https://anaconda.org/conda-forge/pytest-xdist/badges/version.svg + :alt: Anaconda version :target: https://anaconda.org/conda-forge/pytest-xdist .. image:: https://travis-ci.org/pytest-dev/pytest-xdist.svg?branch=master + :alt: Travis CI build status :target: https://travis-ci.org/pytest-dev/pytest-xdist .. image:: https://ci.appveyor.com/api/projects/status/56eq1a1avd4sdd7e/branch/master?svg=true + :alt: AppVeyor build status :target: https://ci.appveyor.com/project/pytestbot/pytest-xdist xdist: pytest distributed testing plugin @@ -238,7 +246,7 @@ .. code-block:: ini [pytest] - addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python2.6 + addopts = --tx ssh=myhost//python=python2.5 --tx ssh=myhost//python=python3.6 and then just type:: @@ -322,6 +330,22 @@ Currently the groupings can't be customized, with grouping by class takes priority over grouping by module. + Sending tests to the same worker based on their file + ++++++++++++++++++++++++++++++++++++++++++++++++++++ + + *New in version 1.21.* + + .. note:: + This is an **experimental** feature: the actual functionality will + likely stay the same, but the CLI might change slightly in future versions. + + You can send tests to the same worker grouped by their filename by using the + ``--dist=loadfile`` option, so tests of the same file are guaranteed to run + in the same worker. + + Using the example in the previous section, all tests from ``test_container.py`` will + run in the same worker, as well as the tests in ``test_io.py``. + Specifying "rsync" dirs in an ini-file +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ @@ -356,4 +380,10 @@ Classifier: Topic :: Software Development :: Quality Assurance Classifier: Topic :: Utilities Classifier: Programming Language :: Python +Classifier: Programming Language :: Python :: 2 +Classifier: Programming Language :: Python :: 2.7 Classifier: Programming Language :: Python :: 3 +Classifier: Programming Language :: Python :: 3.4 +Classifier: Programming Language :: Python :: 3.5 +Classifier: Programming Language :: Python :: 3.6 +Requires-Python: >=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.* diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/pytest_xdist.egg-info/SOURCES.txt new/pytest-xdist-1.21.0/pytest_xdist.egg-info/SOURCES.txt --- old/pytest-xdist-1.20.1/pytest_xdist.egg-info/SOURCES.txt 2017-10-05 22:18:54.000000000 +0200 +++ new/pytest-xdist-1.21.0/pytest_xdist.egg-info/SOURCES.txt 2017-12-26 13:56:21.000000000 +0100 @@ -48,5 +48,6 @@ xdist/slavemanage.py xdist/scheduler/__init__.py xdist/scheduler/each.py +xdist/scheduler/filescope.py xdist/scheduler/load.py xdist/scheduler/loadscope.py \ No newline at end of file diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/setup.py new/pytest-xdist-1.21.0/setup.py --- old/pytest-xdist-1.20.1/setup.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/setup.py 2017-12-26 13:55:58.000000000 +0100 @@ -1,12 +1,7 @@ -from sys import version_info - from setuptools import setup, find_packages install_requires = ['execnet>=1.1', 'pytest>=3.0.0', 'pytest-forked'] -if version_info < (2, 7): - install_requires.append('ordereddict') - setup( name="pytest-xdist", @@ -27,6 +22,7 @@ ], }, zip_safe=False, + python_requires='>=2.7, !=3.0.*, !=3.1.*, !=3.2.*, !=3.3.*', install_requires=install_requires, setup_requires=['setuptools_scm'], classifiers=[ @@ -41,6 +37,11 @@ 'Topic :: Software Development :: Quality Assurance', 'Topic :: Utilities', 'Programming Language :: Python', + 'Programming Language :: Python :: 2', + 'Programming Language :: Python :: 2.7', 'Programming Language :: Python :: 3', + 'Programming Language :: Python :: 3.4', + 'Programming Language :: Python :: 3.5', + 'Programming Language :: Python :: 3.6', ], ) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/acceptance_test.py new/pytest-xdist-1.21.0/testing/acceptance_test.py --- old/pytest-xdist-1.20.1/testing/acceptance_test.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/acceptance_test.py 2017-12-26 13:55:58.000000000 +0100 @@ -755,9 +755,9 @@ with open(fname) as f: worker_ids.add(f.read().strip()) if n == 0: - assert worker_ids == set(['master']) + assert worker_ids == {'master'} else: - assert worker_ids == set(['gw0', 'gw1']) + assert worker_ids == {'gw0', 'gw1'} @pytest.mark.parametrize('tb', @@ -856,11 +856,72 @@ 'test_a.py::TestB', result.outlines) in ({'gw0': 10}, {'gw1': 10}) +class TestFileScope: + + def test_by_module(self, testdir): + test_file = """ + import pytest + class TestA: + @pytest.mark.parametrize('i', range(10)) + def test(self, i): + pass + + class TestB: + @pytest.mark.parametrize('i', range(10)) + def test(self, i): + pass + """ + testdir.makepyfile( + test_a=test_file, + test_b=test_file, + ) + result = testdir.runpytest('-n2', '--dist=loadfile', '-v') + test_a_workers_and_test_count = get_workers_and_test_count_by_prefix( + 'test_a.py::TestA', result.outlines) + test_b_workers_and_test_count = get_workers_and_test_count_by_prefix( + 'test_b.py::TestB', result.outlines) + + assert test_a_workers_and_test_count in ({'gw0': 10}, {'gw1': 0}) or \ + test_a_workers_and_test_count in ({'gw0': 0}, {'gw1': 10}) + assert test_b_workers_and_test_count in ({'gw0': 10}, {'gw1': 0}) or \ + test_b_workers_and_test_count in ({'gw0': 0}, {'gw1': 10}) + + def test_by_class(self, testdir): + testdir.makepyfile(test_a=""" + import pytest + class TestA: + @pytest.mark.parametrize('i', range(10)) + def test(self, i): + pass + + class TestB: + @pytest.mark.parametrize('i', range(10)) + def test(self, i): + pass + """) + result = testdir.runpytest('-n2', '--dist=loadfile', '-v') + test_a_workers_and_test_count = get_workers_and_test_count_by_prefix( + 'test_a.py::TestA', result.outlines) + test_b_workers_and_test_count = get_workers_and_test_count_by_prefix( + 'test_a.py::TestB', result.outlines) + + assert test_a_workers_and_test_count in ({'gw0': 10}, {'gw1': 0}) or \ + test_a_workers_and_test_count in ({'gw0': 0}, {'gw1': 10}) + assert test_b_workers_and_test_count in ({'gw0': 10}, {'gw1': 0}) or \ + test_b_workers_and_test_count in ({'gw0': 0}, {'gw1': 10}) + + def parse_tests_and_workers_from_output(lines): result = [] for line in lines: # example match: "[gw0] PASSED test_a.py::test[7]" - m = re.match(r'\[(gw\d)\]\s(.*?)\s(.*::.*)', line.strip()) + m = re.match(r''' + \[(gw\d)\] # worker + \s* + (?:\[\s*\d+%\])? # progress indicator (pytest >=3.3) + \s(.*?) # status string ("PASSED") + \s(.*::.*) # nodeid + ''', line.strip(), re.VERBOSE) if m: worker, status, nodeid = m.groups() result.append((worker, status, nodeid)) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/conftest.py new/pytest-xdist-1.21.0/testing/conftest.py --- old/pytest-xdist-1.20.1/testing/conftest.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/conftest.py 2017-12-26 13:55:58.000000000 +0100 @@ -20,13 +20,13 @@ @pytest.fixture(autouse=True) def _divert_atexit(request, monkeypatch): import atexit - l = [] + finalizers = [] def finish(): - while l: - l.pop()() + while finalizers: + finalizers.pop()() - monkeypatch.setattr(atexit, "register", l.append) + monkeypatch.setattr(atexit, "register", finalizers.append) request.addfinalizer(finish) @@ -34,7 +34,7 @@ parser.addoption('--gx', action="append", dest="gspecs", - help=("add a global test environment, XSpec-syntax. ")) + help="add a global test environment, XSpec-syntax. ") @pytest.fixture diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/test_dsession.py new/pytest-xdist-1.21.0/testing/test_dsession.py --- old/pytest-xdist-1.20.1/testing/test_dsession.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/test_dsession.py 2017-12-26 13:55:58.000000000 +0100 @@ -126,7 +126,7 @@ sched.add_node(MockNode()) sched.add_node(MockNode()) node1, node2 = sched.nodes - col = ["xyz"] * (6) + col = ["xyz"] * 6 sched.add_node_collection(node1, col) sched.add_node_collection(node2, col) sched.schedule() diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/test_looponfail.py new/pytest-xdist-1.21.0/testing/test_looponfail.py --- old/pytest-xdist-1.20.1/testing/test_looponfail.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/test_looponfail.py 2017-12-26 13:55:58.000000000 +0100 @@ -83,10 +83,10 @@ tmp = tmpdir sd = StatRecorder([tmp]) - l = [True, False] - monkeypatch.setattr(StatRecorder, 'check', lambda self: l.pop()) + ret_values = [True, False] + monkeypatch.setattr(StatRecorder, 'check', lambda self: ret_values.pop()) sd.waitonchange(checkinterval=0.2) - assert not l + assert not ret_values class TestRemoteControl: diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/test_remote.py new/pytest-xdist-1.21.0/testing/test_remote.py --- old/pytest-xdist-1.20.1/testing/test_remote.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/test_remote.py 2017-12-26 13:55:58.000000000 +0100 @@ -79,6 +79,21 @@ class TestReportSerialization: + def test_xdist_longrepr_to_str_issue_241(self, testdir): + testdir.makepyfile(""" + import os + def test_a(): assert False + def test_b(): pass + """) + testdir.makeconftest(""" + def pytest_runtest_logreport(report): + print(report.longrepr) + """) + res = testdir.runpytest('-n1', '-s') + res.stdout.fnmatch_lines([ + '*1 failed, 1 passed *' + ]) + def test_xdist_report_longrepr_reprcrash_130(self, testdir): reprec = testdir.inline_runsource(""" import py @@ -107,8 +122,6 @@ assert rep.longrepr.reprtraceback.style \ == a.longrepr.reprtraceback.style assert rep.longrepr.sections == a.longrepr.sections - assert rep.longrepr.reprtraceback.reprentries \ - == a.longrepr.reprtraceback.reprentries # Missing section attribute PR171 assert added_section in a.longrepr.sections @@ -127,14 +140,15 @@ rep_entries = rep.longrepr.reprtraceback.reprentries a_entries = a.longrepr.reprtraceback.reprentries - assert rep_entries == a_entries for i in range(len(a_entries)): assert isinstance(rep_entries[i], ReprEntry) assert rep_entries[i].lines == a_entries[i].lines assert rep_entries[i].localssep == a_entries[i].localssep - assert rep_entries[i].reprfileloc == a_entries[i].reprfileloc - assert rep_entries[i].reprfuncargs == a_entries[i].reprfuncargs - assert rep_entries[i].reprlocals == a_entries[i].reprlocals + assert rep_entries[i].reprfileloc.lineno == a_entries[i].reprfileloc.lineno + assert rep_entries[i].reprfileloc.message == a_entries[i].reprfileloc.message + assert rep_entries[i].reprfileloc.path == a_entries[i].reprfileloc.path + assert rep_entries[i].reprfuncargs.args == a_entries[i].reprfuncargs.args + assert rep_entries[i].reprlocals.lines == a_entries[i].reprlocals.lines assert rep_entries[i].style == a_entries[i].style def test_reprentries_serialization_196(self, testdir): @@ -152,7 +166,6 @@ rep_entries = rep.longrepr.reprtraceback.reprentries a_entries = a.longrepr.reprtraceback.reprentries - assert rep_entries == a_entries for i in range(len(a_entries)): assert isinstance(rep_entries[i], ReprEntryNative) assert rep_entries[i].lines == a_entries[i].lines diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/testing/test_slavemanage.py new/pytest-xdist-1.21.0/testing/test_slavemanage.py --- old/pytest-xdist-1.20.1/testing/test_slavemanage.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/testing/test_slavemanage.py 2017-12-26 13:55:58.000000000 +0100 @@ -50,10 +50,10 @@ assert gm.specs[0].chdir is None def test_default_chdir(self, config): - l = ["ssh=noco", "socket=xyz"] - for spec in NodeManager(config, l).specs: + specs = ["ssh=noco", "socket=xyz"] + for spec in NodeManager(config, specs).specs: assert spec.chdir == "pyexecnetcache" - for spec in NodeManager(config, l, defaultchdir="abc").specs: + for spec in NodeManager(config, specs, defaultchdir="abc").specs: assert spec.chdir == "abc" def test_popen_makegateway_events(self, config, hookrecorder, @@ -89,10 +89,10 @@ pass gw.remote_exec = pseudoexec - l = [] + notifications = [] for gw in hm.group: - hm.rsync(gw, source, notify=lambda *args: l.append(args)) - assert not l + hm.rsync(gw, source, notify=lambda *args: notifications.append(args)) + assert not notifications hm.teardown_nodes() assert not len(hm.group) assert "sys.path.insert" in gw.remote_exec.args[0] @@ -102,11 +102,11 @@ hm = NodeManager(config, ["popen//chdir=%s" % dest] * 1) hm.setup_nodes(None) source.ensure("dir1", "dir2", "hello") - l = [] + notifications = [] for gw in hm.group: - hm.rsync(gw, source, notify=lambda *args: l.append(args)) - assert len(l) == 1 - assert l[0] == ("rsyncrootready", hm.group['gw0'].spec, source) + hm.rsync(gw, source, notify=lambda *args: notifications.append(args)) + assert len(notifications) == 1 + assert notifications[0] == ("rsyncrootready", hm.group['gw0'].spec, source) hm.teardown_nodes() dest = dest.join(source.basename) assert dest.join("dir1").check() @@ -137,9 +137,9 @@ source.ensure(".somedotfile", "moreentries") source.ensure("somedir", "editfile~") syncer = HostRSync(source, ignores=NodeManager.DEFAULT_IGNORES) - l = list(source.visit(rec=syncer.filter, fil=syncer.filter)) - assert len(l) == 3 - basenames = [x.basename for x in l] + files = list(source.visit(rec=syncer.filter, fil=syncer.filter)) + assert len(files) == 3 + basenames = [x.basename for x in files] assert 'dir' in basenames assert 'file.txt' in basenames assert 'somedir' in basenames diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/tox.ini new/pytest-xdist-1.21.0/tox.ini --- old/pytest-xdist-1.20.1/tox.ini 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/tox.ini 2017-12-26 13:55:58.000000000 +0100 @@ -1,8 +1,8 @@ [tox] # if you change the envlist, please update .travis.yml file as well envlist= - py{26,27,34,35,36}-pytest{30,31,32} - py{27,36}-pytest{30,31,32}-pexpect + py{27,34,35,36}-pytest{30,31,32,33} + py{27,36}-pytest{30,31,32,33}-pexpect py{27,36}-pytest{master,features} flakes readme @@ -18,6 +18,7 @@ pytest30: pytest~=3.0.5 pytest31: pytest~=3.1.0 pytest32: pytest~=3.2.0 + pytest33: pytest~=3.3.0 pytestmaster: git+https://github.com/pytest-dev/pytest.git@master pytestfeatures: git+https://github.com/pytest-dev/pytest.git@features pexpect: pexpect diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/_version.py new/pytest-xdist-1.21.0/xdist/_version.py --- old/pytest-xdist-1.20.1/xdist/_version.py 2017-10-05 22:18:54.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/_version.py 2017-12-26 13:56:21.000000000 +0100 @@ -1,4 +1,4 @@ # coding: utf-8 # file generated by setuptools_scm # don't change, don't track in version control -version = '1.20.1' +version = '1.21.0' diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/dsession.py new/pytest-xdist-1.21.0/xdist/dsession.py --- old/pytest-xdist-1.20.1/xdist/dsession.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/dsession.py 2017-12-26 13:55:58.000000000 +0100 @@ -6,6 +6,7 @@ EachScheduling, LoadScheduling, LoadScopeScheduling, + LoadFileScheduling, ) @@ -99,6 +100,7 @@ 'each': EachScheduling, 'load': LoadScheduling, 'loadscope': LoadScopeScheduling, + 'loadfile': LoadFileScheduling, } return schedulers[dist](config, log) diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/plugin.py new/pytest-xdist-1.21.0/xdist/plugin.py --- old/pytest-xdist-1.20.1/xdist/plugin.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/plugin.py 2017-12-26 13:55:58.000000000 +0100 @@ -31,7 +31,7 @@ "when crashed (set to zero to disable this feature)") group.addoption( '--dist', metavar="distmode", - action="store", choices=['each', 'load', 'loadscope', 'no'], + action="store", choices=['each', 'load', 'loadscope', 'loadfile', 'no'], dest="dist", default="no", help=("set mode for distributing tests to exec environments.\n\n" "each: send each test to all available environments.\n\n" @@ -39,6 +39,8 @@ " available environment.\n\n" "loadscope: load balance by sending pending groups of tests in" " the same scope to any available environment.\n\n" + "loadfile: load balance by sending test grouped by file" + " to any available environment.\n\n" "(default) no: run tests inprocess, don't distribute.")) group.addoption( '--tx', dest="tx", action="append", default=[], diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/remote.py new/pytest-xdist-1.21.0/xdist/remote.py --- old/pytest-xdist-1.20.1/xdist/remote.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/remote.py 2017-12-26 13:55:58.000000000 +0100 @@ -111,18 +111,18 @@ def serialize_report(rep): def disassembled_report(rep): - reprtraceback = rep.longrepr.reprtraceback.__dict__ - reprcrash = rep.longrepr.reprcrash.__dict__ + reprtraceback = rep.longrepr.reprtraceback.__dict__.copy() + reprcrash = rep.longrepr.reprcrash.__dict__.copy() new_entries = [] for entry in reprtraceback['reprentries']: entry_data = { 'type': type(entry).__name__, - 'data': entry.__dict__, + 'data': entry.__dict__.copy(), } for key, value in entry_data['data'].items(): if hasattr(value, '__dict__'): - entry_data['data'][key] = value.__dict__ + entry_data['data'][key] = value.__dict__.copy() new_entries.append(entry_data) reprtraceback['reprentries'] = new_entries @@ -178,10 +178,6 @@ if __name__ == '__channelexec__': channel = channel # noqa - # python3.2 is not concurrent import safe, so let's play it safe - # https://bitbucket.org/hpk42/pytest/issue/347/pytest-xdist-and-python-32 - if sys.version_info[:2] == (3, 2): - os.environ["PYTHONDONTWRITEBYTECODE"] = "1" slaveinput, args, option_dict = channel.receive() importpath = os.getcwd() sys.path.insert(0, importpath) # XXX only for remote situations diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/scheduler/__init__.py new/pytest-xdist-1.21.0/xdist/scheduler/__init__.py --- old/pytest-xdist-1.20.1/xdist/scheduler/__init__.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/scheduler/__init__.py 2017-12-26 13:55:58.000000000 +0100 @@ -1,3 +1,4 @@ from xdist.scheduler.each import EachScheduling # noqa from xdist.scheduler.load import LoadScheduling # noqa from xdist.scheduler.loadscope import LoadScopeScheduling # noqa +from xdist.scheduler.filescope import LoadFileScheduling # noqa diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/scheduler/filescope.py new/pytest-xdist-1.21.0/xdist/scheduler/filescope.py --- old/pytest-xdist-1.20.1/xdist/scheduler/filescope.py 1970-01-01 01:00:00.000000000 +0100 +++ new/pytest-xdist-1.21.0/xdist/scheduler/filescope.py 2017-12-26 13:55:58.000000000 +0100 @@ -0,0 +1,52 @@ +from . import LoadScopeScheduling +from py.log import Producer + + +class LoadFileScheduling(LoadScopeScheduling): + """Implement load scheduling across nodes, but grouping test test file. + + This distributes the tests collected across all nodes so each test is run + just once. All nodes collect and submit the list of tests and when all + collections are received it is verified they are identical collections. + Then the collection gets divided up in work units, grouped by test file, + and those work units get submitted to nodes. Whenever a node finishes an + item, it calls ``.mark_test_complete()`` which will trigger the scheduler + to assign more work units if the number of pending tests for the node falls + below a low-watermark. + + When created, ``numnodes`` defines how many nodes are expected to submit a + collection. This is used to know when all nodes have finished collection. + + This class behaves very much like LoadScopeScheduling, but with a file-level scope. + """ + + def __init(self, config, log=None): + super(LoadFileScheduling, self).__init__(config, log) + if log is None: + self.log = Producer('loadfilesched') + else: + self.log = log.loadfilesched + + def _split_scope(self, nodeid): + """Determine the scope (grouping) of a nodeid. + + There are usually 3 cases for a nodeid:: + + example/loadsuite/test/test_beta.py::test_beta0 + example/loadsuite/test/test_delta.py::Delta1::test_delta0 + example/loadsuite/epsilon/__init__.py::epsilon.epsilon + + #. Function in a test module. + #. Method of a class in a test module. + #. Doctest in a function in a package. + + This function will group tests with the scope determined by splitting + the first ``::`` from the left. That is, test will be grouped in a + single work unit when they reside in the same file. + In the above example, scopes will be:: + + example/loadsuite/test/test_beta.py + example/loadsuite/test/test_delta.py + example/loadsuite/epsilon/__init__.py + """ + return nodeid.split('::', 1)[0] diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/scheduler/loadscope.py new/pytest-xdist-1.21.0/xdist/scheduler/loadscope.py --- old/pytest-xdist-1.20.1/xdist/scheduler/loadscope.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/scheduler/loadscope.py 2017-12-26 13:55:58.000000000 +0100 @@ -1,14 +1,9 @@ -try: - from collections import OrderedDict -except ImportError: - # Support for Python 2.6 - from ordereddict import OrderedDict +from collections import OrderedDict -from py.log import Producer from _pytest.runner import CollectReport - -from xdist.slavemanage import parse_spec_config +from py.log import Producer from xdist.report import report_collection_diff +from xdist.slavemanage import parse_spec_config class LoadScopeScheduling: @@ -373,12 +368,12 @@ extra_nodes = len(self.nodes) - len(self.workqueue) if extra_nodes > 0: - self.log('Shuting down {} nodes'.format(extra_nodes)) + self.log('Shuting down {0} nodes'.format(extra_nodes)) for _ in range(extra_nodes): unused_node, assigned = self.assigned_work.popitem(last=True) - self.log('Shuting down unused node {}'.format(unused_node)) + self.log('Shuting down unused node {0}'.format(unused_node)) unused_node.shutdown() # Assign initial workload diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' '--exclude=.svnignore' old/pytest-xdist-1.20.1/xdist/slavemanage.py new/pytest-xdist-1.21.0/xdist/slavemanage.py --- old/pytest-xdist-1.20.1/xdist/slavemanage.py 2017-10-05 22:18:37.000000000 +0200 +++ new/pytest-xdist-1.21.0/xdist/slavemanage.py 2017-12-26 13:55:58.000000000 +0100 @@ -186,7 +186,7 @@ def make_reltoroot(roots, args): # XXX introduce/use public API for splitting py.test args splitcode = "::" - l = [] + result = [] for arg in args: parts = arg.split(splitcode) fspath = py.path.local(parts[0]) @@ -197,8 +197,8 @@ break else: raise ValueError("arg %s not relative to an rsync root" % (arg,)) - l.append(splitcode.join(parts)) - return l + result.append(splitcode.join(parts)) + return result class SlaveController(object): @@ -326,7 +326,7 @@ except KeyboardInterrupt: # should not land in receiver-thread raise - except: + except: # noqa excinfo = py.code.ExceptionInfo() py.builtin.print_("!" * 20, excinfo) self.config.notify_exception(excinfo)