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)


Reply via email to