Hello community,

here is the log from the commit of package python-pytest4 for openSUSE:Factory 
checked in at 2019-08-27 15:20:38
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest4 (Old)
 and      /work/SRC/openSUSE:Factory/.python-pytest4.new.7948 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pytest4"

Tue Aug 27 15:20:38 2019 rev:7 rq:724497 version:4.6.5

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest4/python-pytest4.changes    
2019-07-30 13:02:03.134430645 +0200
+++ /work/SRC/openSUSE:Factory/.python-pytest4.new.7948/python-pytest4.changes  
2019-08-27 15:20:39.908862643 +0200
@@ -1,0 +2,11 @@
+Mon Aug 19 08:18:32 UTC 2019 - Tomáš Chvátal <[email protected]>
+
+- Update to 4.6.5:
+  * #4344: Fix RuntimeError/StopIteration when trying to collect package with 
"init.py" only.
+  * #5478: Fix encode error when using unicode strings in exceptions with 
pytest.raises.
+  * #5524: Fix issue where tmp_path and tmpdir would not remove directories 
containing files marked as read-only,
+           which could lead to pytest crashing when executed a second time 
with the --basetemp option.
+  * #5547: --step-wise now handles xfail(strict=True) markers properly.
+  * #5650: Improved output when parsing an ini configuration file fails.
+
+-------------------------------------------------------------------

Old:
----
  pytest-4.6.4.tar.gz

New:
----
  pytest-4.6.5.tar.gz

++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Other differences:
------------------
++++++ python-pytest4.spec ++++++
--- /var/tmp/diff_new_pack.onDhOZ/_old  2019-08-27 15:20:40.476862356 +0200
+++ /var/tmp/diff_new_pack.onDhOZ/_new  2019-08-27 15:20:40.480862354 +0200
@@ -26,7 +26,7 @@
 %bcond_with test
 %endif
 Name:           python-pytest4%{psuffix}
-Version:        4.6.4
+Version:        4.6.5
 Release:        0
 Summary:        Python testing tool with autodiscovery and detailed asserts
 License:        MIT

++++++ pytest-4.6.4.tar.gz -> pytest-4.6.5.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/.travis.yml new/pytest-4.6.5/.travis.yml
--- old/pytest-4.6.4/.travis.yml        2019-06-29 04:00:08.000000000 +0200
+++ new/pytest-4.6.5/.travis.yml        2019-08-05 20:04:19.000000000 +0200
@@ -13,6 +13,10 @@
   global:
     - PYTEST_ADDOPTS=-vv
 
+# setuptools-scm needs all tags in order to obtain a proper version
+git:
+  depth: false
+
 install:
   - python -m pip install --upgrade --pre tox
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/CHANGELOG.rst 
new/pytest-4.6.5/CHANGELOG.rst
--- old/pytest-4.6.4/CHANGELOG.rst      2019-06-29 04:00:08.000000000 +0200
+++ new/pytest-4.6.5/CHANGELOG.rst      2019-08-05 20:04:19.000000000 +0200
@@ -18,6 +18,28 @@
 
 .. towncrier release notes start
 
+pytest 4.6.5 (2019-08-05)
+=========================
+
+Bug Fixes
+---------
+
+- `#4344 <https://github.com/pytest-dev/pytest/issues/4344>`_: Fix 
RuntimeError/StopIteration when trying to collect package with "__init__.py" 
only.
+
+
+- `#5478 <https://github.com/pytest-dev/pytest/issues/5478>`_: Fix encode 
error when using unicode strings in exceptions with ``pytest.raises``.
+
+
+- `#5524 <https://github.com/pytest-dev/pytest/issues/5524>`_: Fix issue where 
``tmp_path`` and ``tmpdir`` would not remove directories containing files 
marked as read-only,
+  which could lead to pytest crashing when executed a second time with the 
``--basetemp`` option.
+
+
+- `#5547 <https://github.com/pytest-dev/pytest/issues/5547>`_: ``--step-wise`` 
now handles ``xfail(strict=True)`` markers properly.
+
+
+- `#5650 <https://github.com/pytest-dev/pytest/issues/5650>`_: Improved output 
when parsing an ini configuration file fails.
+
+
 pytest 4.6.4 (2019-06-28)
 =========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/PKG-INFO new/pytest-4.6.5/PKG-INFO
--- old/pytest-4.6.4/PKG-INFO   2019-06-29 04:00:24.000000000 +0200
+++ new/pytest-4.6.5/PKG-INFO   2019-08-05 20:04:36.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pytest
-Version: 4.6.4
+Version: 4.6.5
 Summary: pytest: simple powerful testing with Python
 Home-page: https://docs.pytest.org/en/latest/
 Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, 
Brianna Laugher, Florian Bruhin and others
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/doc/en/announce/index.rst 
new/pytest-4.6.5/doc/en/announce/index.rst
--- old/pytest-4.6.4/doc/en/announce/index.rst  2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/doc/en/announce/index.rst  2019-08-05 20:04:19.000000000 
+0200
@@ -6,6 +6,7 @@
    :maxdepth: 2
 
 
+   release-4.6.5
    release-4.6.4
    release-4.6.3
    release-4.6.2
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/doc/en/announce/release-4.6.5.rst 
new/pytest-4.6.5/doc/en/announce/release-4.6.5.rst
--- old/pytest-4.6.4/doc/en/announce/release-4.6.5.rst  1970-01-01 
01:00:00.000000000 +0100
+++ new/pytest-4.6.5/doc/en/announce/release-4.6.5.rst  2019-08-05 
20:04:19.000000000 +0200
@@ -0,0 +1,21 @@
+pytest-4.6.5
+=======================================
+
+pytest 4.6.5 has just been released to PyPI.
+
+This is a bug-fix release, being a drop-in replacement. To upgrade::
+
+  pip install --upgrade pytest
+
+The full changelog is available at 
https://docs.pytest.org/en/latest/changelog.html.
+
+Thanks to all who contributed to this release, among them:
+
+* Anthony Sottile
+* Bruno Oliveira
+* Daniel Hahler
+* Thomas Grainger
+
+
+Happy testing,
+The pytest Development Team
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/doc/en/example/parametrize.rst 
new/pytest-4.6.5/doc/en/example/parametrize.rst
--- old/pytest-4.6.4/doc/en/example/parametrize.rst     2019-06-29 
04:00:08.000000000 +0200
+++ new/pytest-4.6.5/doc/en/example/parametrize.rst     2019-08-05 
20:04:19.000000000 +0200
@@ -434,10 +434,11 @@
 .. code-block:: pytest
 
    . $ pytest -rs -q multipython.py
-   ...sss...sssssssss...sss...                                          [100%]
+   ...ssssssssssssssssssssssss                                          [100%]
    ========================= short test summary info ==========================
-   SKIPPED [15] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.4' not found
-   12 passed, 15 skipped in 0.12 seconds
+   SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.4' not found
+   SKIPPED [12] $REGENDOC_TMPDIR/CWD/multipython.py:31: 'python3.5' not found
+   3 passed, 24 skipped in 0.12 seconds
 
 Indirect parametrization of optional implementations/imports
 --------------------------------------------------------------------
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/doc/en/example/simple.rst 
new/pytest-4.6.5/doc/en/example/simple.rst
--- old/pytest-4.6.4/doc/en/example/simple.rst  2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/doc/en/example/simple.rst  2019-08-05 20:04:19.000000000 
+0200
@@ -440,7 +440,7 @@
     test_some_are_slow.py ...                                            [100%]
 
     ========================= slowest 3 test durations 
=========================
-    0.30s call     test_some_are_slow.py::test_funcslow2
+    0.31s call     test_some_are_slow.py::test_funcslow2
     0.20s call     test_some_are_slow.py::test_funcslow1
     0.10s call     test_some_are_slow.py::test_funcfast
     ========================= 3 passed in 0.12 seconds 
=========================
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/_code/code.py 
new/pytest-4.6.5/src/_pytest/_code/code.py
--- old/pytest-4.6.4/src/_pytest/_code/code.py  2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/src/_pytest/_code/code.py  2019-08-05 20:04:19.000000000 
+0200
@@ -572,8 +572,13 @@
         raised.
         """
         __tracebackhide__ = True
-        if not re.search(regexp, str(self.value)):
-            assert 0, "Pattern '{!s}' not found in '{!s}'".format(regexp, 
self.value)
+        value = (
+            text_type(self.value) if isinstance(regexp, text_type) else 
str(self.value)
+        )
+        if not re.search(regexp, value):
+            raise AssertionError(
+                u"Pattern {!r} not found in {!r}".format(regexp, value)
+            )
         return True
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/_version.py 
new/pytest-4.6.5/src/_pytest/_version.py
--- old/pytest-4.6.4/src/_pytest/_version.py    2019-06-29 04:00:23.000000000 
+0200
+++ new/pytest-4.6.5/src/_pytest/_version.py    2019-08-05 20:04:36.000000000 
+0200
@@ -1,4 +1,4 @@
 # coding: utf-8
 # file generated by setuptools_scm
 # don't change, don't track in version control
-version = '4.6.4'
+version = '4.6.5'
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/cacheprovider.py 
new/pytest-4.6.5/src/_pytest/cacheprovider.py
--- old/pytest-4.6.4/src/_pytest/cacheprovider.py       2019-06-29 
04:00:08.000000000 +0200
+++ new/pytest-4.6.5/src/_pytest/cacheprovider.py       2019-08-05 
20:04:19.000000000 +0200
@@ -21,7 +21,7 @@
 from .compat import _PY2 as PY2
 from .pathlib import Path
 from .pathlib import resolve_from_str
-from .pathlib import rmtree
+from .pathlib import rm_rf
 
 README_CONTENT = u"""\
 # pytest cache directory #
@@ -51,7 +51,7 @@
     def for_config(cls, config):
         cachedir = cls.cache_dir_from_config(config)
         if config.getoption("cacheclear") and cachedir.exists():
-            rmtree(cachedir, force=True)
+            rm_rf(cachedir)
             cachedir.mkdir()
         return cls(cachedir, config)
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/config/findpaths.py 
new/pytest-4.6.5/src/_pytest/config/findpaths.py
--- old/pytest-4.6.4/src/_pytest/config/findpaths.py    2019-06-29 
04:00:08.000000000 +0200
+++ new/pytest-4.6.5/src/_pytest/config/findpaths.py    2019-08-05 
20:04:19.000000000 +0200
@@ -33,7 +33,11 @@
             for inibasename in inibasenames:
                 p = base.join(inibasename)
                 if exists(p):
-                    iniconfig = py.iniconfig.IniConfig(p)
+                    try:
+                        iniconfig = py.iniconfig.IniConfig(p)
+                    except py.iniconfig.ParseError as exc:
+                        raise UsageError(str(exc))
+
                     if (
                         inibasename == "setup.cfg"
                         and "tool:pytest" in iniconfig.sections
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/main.py 
new/pytest-4.6.5/src/_pytest/main.py
--- old/pytest-4.6.4/src/_pytest/main.py        2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/src/_pytest/main.py        2019-08-05 20:04:19.000000000 
+0200
@@ -621,7 +621,13 @@
             # Module itself, so just use that. If this special case isn't 
taken, then all
             # the files in the package will be yielded.
             if argpath.basename == "__init__.py":
-                yield next(m[0].collect())
+                try:
+                    yield next(m[0].collect())
+                except StopIteration:
+                    # The package collects nothing with only an __init__.py
+                    # file in it, which gets ignored by the default
+                    # "python_files" option.
+                    pass
                 return
             for y in m:
                 yield y
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/pathlib.py 
new/pytest-4.6.5/src/_pytest/pathlib.py
--- old/pytest-4.6.4/src/_pytest/pathlib.py     2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/src/_pytest/pathlib.py     2019-08-05 20:04:19.000000000 
+0200
@@ -1,4 +1,6 @@
 # -*- coding: utf-8 -*-
+from __future__ import absolute_import
+
 import atexit
 import errno
 import fnmatch
@@ -8,6 +10,8 @@
 import shutil
 import sys
 import uuid
+import warnings
+from functools import partial
 from functools import reduce
 from os.path import expanduser
 from os.path import expandvars
@@ -19,6 +23,7 @@
 from six.moves import map
 
 from .compat import PY36
+from _pytest.warning_types import PytestWarning
 
 if PY36:
     from pathlib import Path, PurePath
@@ -38,17 +43,57 @@
     ensures the given path is an empty directory
     """
     if path.exists():
-        rmtree(path, force=True)
+        rm_rf(path)
     path.mkdir()
 
 
-def rmtree(path, force=False):
-    if force:
-        # NOTE: ignore_errors might leave dead folders around.
-        #       Python needs a rm -rf as a followup.
-        shutil.rmtree(str(path), ignore_errors=True)
-    else:
-        shutil.rmtree(str(path))
+def on_rm_rf_error(func, path, exc, **kwargs):
+    """Handles known read-only errors during rmtree."""
+    start_path = kwargs["start_path"]
+    excvalue = exc[1]
+
+    if not isinstance(excvalue, OSError) or excvalue.errno not in (
+        errno.EACCES,
+        errno.EPERM,
+    ):
+        warnings.warn(
+            PytestWarning("(rm_rf) error removing {}: {}".format(path, 
excvalue))
+        )
+        return
+
+    if func not in (os.rmdir, os.remove, os.unlink):
+        warnings.warn(
+            PytestWarning("(rm_rf) error removing {}: {}".format(path, 
excvalue))
+        )
+        return
+
+    # Chmod + retry.
+    import stat
+
+    def chmod_rw(p):
+        mode = os.stat(p).st_mode
+        os.chmod(p, mode | stat.S_IRUSR | stat.S_IWUSR)
+
+    # For files, we need to recursively go upwards in the directories to
+    # ensure they all are also writable.
+    p = Path(path)
+    if p.is_file():
+        for parent in p.parents:
+            chmod_rw(str(parent))
+            # stop when we reach the original path passed to rm_rf
+            if parent == start_path:
+                break
+    chmod_rw(str(path))
+
+    func(path)
+
+
+def rm_rf(path):
+    """Remove the path contents recursively, even if some elements
+    are read-only.
+    """
+    onerror = partial(on_rm_rf_error, start_path=path)
+    shutil.rmtree(str(path), onerror=onerror)
 
 
 def find_prefixed(root, prefix):
@@ -186,7 +231,7 @@
 
         garbage = parent.joinpath("garbage-{}".format(uuid.uuid4()))
         path.rename(garbage)
-        rmtree(garbage, force=True)
+        rm_rf(garbage)
     except (OSError, EnvironmentError):
         #  known races:
         #  * other process did a cleanup at the same time
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/_pytest/stepwise.py 
new/pytest-4.6.5/src/_pytest/stepwise.py
--- old/pytest-4.6.4/src/_pytest/stepwise.py    2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/src/_pytest/stepwise.py    2019-08-05 20:04:19.000000000 
+0200
@@ -72,8 +72,7 @@
         config.hook.pytest_deselected(items=already_passed)
 
     def pytest_runtest_logreport(self, report):
-        # Skip this hook if plugin is not active or the test is xfailed.
-        if not self.active or "xfail" in report.keywords:
+        if not self.active:
             return
 
         if report.failed:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/pytest.egg-info/PKG-INFO 
new/pytest-4.6.5/src/pytest.egg-info/PKG-INFO
--- old/pytest-4.6.4/src/pytest.egg-info/PKG-INFO       2019-06-29 
04:00:23.000000000 +0200
+++ new/pytest-4.6.5/src/pytest.egg-info/PKG-INFO       2019-08-05 
20:04:36.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pytest
-Version: 4.6.4
+Version: 4.6.5
 Summary: pytest: simple powerful testing with Python
 Home-page: https://docs.pytest.org/en/latest/
 Author: Holger Krekel, Bruno Oliveira, Ronny Pfannschmidt, Floris Bruynooghe, 
Brianna Laugher, Florian Bruhin and others
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/src/pytest.egg-info/SOURCES.txt 
new/pytest-4.6.5/src/pytest.egg-info/SOURCES.txt
--- old/pytest-4.6.4/src/pytest.egg-info/SOURCES.txt    2019-06-29 
04:00:24.000000000 +0200
+++ new/pytest-4.6.5/src/pytest.egg-info/SOURCES.txt    2019-08-05 
20:04:36.000000000 +0200
@@ -198,6 +198,7 @@
 doc/en/announce/release-4.6.2.rst
 doc/en/announce/release-4.6.3.rst
 doc/en/announce/release-4.6.4.rst
+doc/en/announce/release-4.6.5.rst
 doc/en/announce/sprint2016.rst
 doc/en/example/attic.rst
 doc/en/example/conftest.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/python/raises.py 
new/pytest-4.6.5/testing/python/raises.py
--- old/pytest-4.6.4/testing/python/raises.py   2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/python/raises.py   2019-08-05 20:04:19.000000000 
+0200
@@ -4,6 +4,7 @@
 import six
 
 import pytest
+from _pytest.compat import dummy_context_manager
 from _pytest.outcomes import Failed
 from _pytest.warning_types import PytestDeprecationWarning
 
@@ -220,7 +221,7 @@
             int("asdf")
 
         msg = "with base 16"
-        expr = r"Pattern '{}' not found in 'invalid literal for int\(\) with 
base 10: 'asdf''".format(
+        expr = r"Pattern '{}' not found in \"invalid literal for int\(\) with 
base 10: 'asdf'\"".format(
             msg
         )
         with pytest.raises(AssertionError, match=expr):
@@ -278,3 +279,47 @@
                 with pytest.raises(CrappyClass()):
                     pass
             assert "via __class__" in excinfo.value.args[0]
+
+
+class TestUnicodeHandling:
+    """Test various combinations of bytes and unicode with pytest.raises 
(#5478)
+
+    https://github.com/pytest-dev/pytest/pull/5479#discussion_r298852433
+    """
+
+    success = dummy_context_manager
+    py2_only = pytest.mark.skipif(
+        six.PY3, reason="bytes in raises only supported in Python 2"
+    )
+
+    @pytest.mark.parametrize(
+        "message, match, expectation",
+        [
+            (u"\u2603", u"\u2603", success()),
+            (u"\u2603", u"\u2603foo", pytest.raises(AssertionError)),
+            pytest.param(b"hello", b"hello", success(), marks=py2_only),
+            pytest.param(
+                b"hello", b"world", pytest.raises(AssertionError), 
marks=py2_only
+            ),
+            pytest.param(u"hello", b"hello", success(), marks=py2_only),
+            pytest.param(
+                u"hello", b"world", pytest.raises(AssertionError), 
marks=py2_only
+            ),
+            pytest.param(
+                u"😊".encode("UTF-8"),
+                b"world",
+                pytest.raises(AssertionError),
+                marks=py2_only,
+            ),
+            pytest.param(
+                u"world",
+                u"😊".encode("UTF-8"),
+                pytest.raises(AssertionError),
+                marks=py2_only,
+            ),
+        ],
+    )
+    def test_handling(self, message, match, expectation):
+        with expectation:
+            with pytest.raises(RuntimeError, match=match):
+                raise RuntimeError(message)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/test_collection.py 
new/pytest-4.6.5/testing/test_collection.py
--- old/pytest-4.6.4/testing/test_collection.py 2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/test_collection.py 2019-08-05 20:04:19.000000000 
+0200
@@ -1211,6 +1211,18 @@
     )
 
 
+def test_collect_pkg_init_only(testdir):
+    subdir = testdir.mkdir("sub")
+    init = subdir.ensure("__init__.py")
+    init.write("def test_init(): pass")
+
+    result = testdir.runpytest(str(init))
+    result.stdout.fnmatch_lines(["*no tests ran in*"])
+
+    result = testdir.runpytest("-v", "-o", "python_files=*.py", str(init))
+    result.stdout.fnmatch_lines(["sub/__init__.py::test_init PASSED*", "*1 
passed in*"])
+
+
 @pytest.mark.skipif(
     not hasattr(py.path.local, "mksymlinkto"),
     reason="symlink not available on this platform",
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/test_config.py 
new/pytest-4.6.5/testing/test_config.py
--- old/pytest-4.6.4/testing/test_config.py     2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/test_config.py     2019-08-05 20:04:19.000000000 
+0200
@@ -131,6 +131,12 @@
         config = testdir.parseconfigure(sub)
         assert config.getini("minversion") == "2.0"
 
+    def test_ini_parse_error(self, testdir):
+        testdir.tmpdir.join("pytest.ini").write("addopts = -x")
+        result = testdir.runpytest()
+        assert result.ret != 0
+        result.stderr.fnmatch_lines(["ERROR: *pytest.ini:1: no section header 
defined"])
+
     @pytest.mark.xfail(reason="probably not needed")
     def test_confcutdir(self, testdir):
         sub = testdir.mkdir("sub")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/test_pytester.py 
new/pytest-4.6.5/testing/test_pytester.py
--- old/pytest-4.6.4/testing/test_pytester.py   2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/test_pytester.py   2019-08-05 20:04:19.000000000 
+0200
@@ -245,8 +245,8 @@
     ):
         spy_factory = self.spy_factory()
         monkeypatch.setattr(pytester, "SysModulesSnapshot", spy_factory)
-        original = dict(sys.modules)
         testdir.syspathinsert()
+        original = dict(sys.modules)
         testdir.makepyfile(import1="# you son of a silly person")
         testdir.makepyfile(import2="# my hovercraft is full of eels")
         test_mod = testdir.makepyfile(
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/test_stepwise.py 
new/pytest-4.6.5/testing/test_stepwise.py
--- old/pytest-4.6.4/testing/test_stepwise.py   2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/test_stepwise.py   2019-08-05 20:04:19.000000000 
+0200
@@ -1,4 +1,6 @@
 # -*- coding: utf-8 -*-
+import sys
+
 import pytest
 
 
@@ -166,3 +168,57 @@
         files.reverse()
     result = broken_testdir.runpytest("-v", "--strict-markers", "--stepwise", 
*files)
     result.stdout.fnmatch_lines("*errors during collection*")
+
+
+def test_xfail_handling(testdir):
+    """Ensure normal xfail is ignored, and strict xfail interrupts the session 
in sw mode
+
+    (#5547)
+    """
+    contents = """
+        import pytest
+        def test_a(): pass
+
+        @pytest.mark.xfail(strict={strict})
+        def test_b(): assert {assert_value}
+
+        def test_c(): pass
+        def test_d(): pass
+    """
+    testdir.makepyfile(contents.format(assert_value="0", strict="False"))
+    result = testdir.runpytest("--sw", "-v")
+    result.stdout.fnmatch_lines(
+        [
+            "*::test_a PASSED *",
+            "*::test_b XFAIL *",
+            "*::test_c PASSED *",
+            "*::test_d PASSED *",
+            "* 3 passed, 1 xfailed in *",
+        ]
+    )
+
+    testdir.makepyfile(contents.format(assert_value="1", strict="True"))
+    result = testdir.runpytest("--sw", "-v")
+    result.stdout.fnmatch_lines(
+        [
+            "*::test_a PASSED *",
+            "*::test_b FAILED *",
+            "* Interrupted*",
+            "* 1 failed, 1 passed in *",
+        ]
+    )
+
+    # because we are writing to the same file, mtime might not be affected 
enough to
+    # invalidate the cache, making this next run flaky
+    if not sys.dont_write_bytecode:
+        testdir.tmpdir.join("__pycache__").remove()
+    testdir.makepyfile(contents.format(assert_value="0", strict="True"))
+    result = testdir.runpytest("--sw", "-v")
+    result.stdout.fnmatch_lines(
+        [
+            "*::test_b XFAIL *",
+            "*::test_c PASSED *",
+            "*::test_d PASSED *",
+            "* 2 passed, 1 deselected, 1 xfailed in *",
+        ]
+    )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-4.6.4/testing/test_tmpdir.py 
new/pytest-4.6.5/testing/test_tmpdir.py
--- old/pytest-4.6.4/testing/test_tmpdir.py     2019-06-29 04:00:08.000000000 
+0200
+++ new/pytest-4.6.5/testing/test_tmpdir.py     2019-08-05 20:04:19.000000000 
+0200
@@ -3,6 +3,9 @@
 from __future__ import division
 from __future__ import print_function
 
+import errno
+import os
+import stat
 import sys
 
 import attr
@@ -317,12 +320,25 @@
             p, consider_lock_dead_if_created_before=p.stat().st_mtime + 1
         )
 
-    def test_rmtree(self, tmp_path):
-        from _pytest.pathlib import rmtree
+    def test_cleanup_ignores_symlink(self, tmp_path):
+        the_symlink = tmp_path / (self.PREFIX + "current")
+        attempt_symlink_to(the_symlink, tmp_path / (self.PREFIX + "5"))
+        self._do_cleanup(tmp_path)
+
+    def test_removal_accepts_lock(self, tmp_path):
+        folder = pathlib.make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
+        pathlib.create_cleanup_lock(folder)
+        pathlib.maybe_delete_a_numbered_dir(folder)
+        assert folder.is_dir()
+
+
+class TestRmRf:
+    def test_rm_rf(self, tmp_path):
+        from _pytest.pathlib import rm_rf
 
         adir = tmp_path / "adir"
         adir.mkdir()
-        rmtree(adir)
+        rm_rf(adir)
 
         assert not adir.exists()
 
@@ -330,19 +346,70 @@
         afile = adir / "afile"
         afile.write_bytes(b"aa")
 
-        rmtree(adir, force=True)
+        rm_rf(adir)
         assert not adir.exists()
 
-    def test_cleanup_ignores_symlink(self, tmp_path):
-        the_symlink = tmp_path / (self.PREFIX + "current")
-        attempt_symlink_to(the_symlink, tmp_path / (self.PREFIX + "5"))
-        self._do_cleanup(tmp_path)
+    def test_rm_rf_with_read_only_file(self, tmp_path):
+        """Ensure rm_rf can remove directories with read-only files in them 
(#5524)"""
+        from _pytest.pathlib import rm_rf
 
-    def test_removal_accepts_lock(self, tmp_path):
-        folder = pathlib.make_numbered_dir(root=tmp_path, prefix=self.PREFIX)
-        pathlib.create_cleanup_lock(folder)
-        pathlib.maybe_delete_a_numbered_dir(folder)
-        assert folder.is_dir()
+        fn = tmp_path / "dir/foo.txt"
+        fn.parent.mkdir()
+
+        fn.touch()
+
+        self.chmod_r(fn)
+
+        rm_rf(fn.parent)
+
+        assert not fn.parent.is_dir()
+
+    def chmod_r(self, path):
+        mode = os.stat(str(path)).st_mode
+        os.chmod(str(path), mode & ~stat.S_IWRITE)
+
+    def test_rm_rf_with_read_only_directory(self, tmp_path):
+        """Ensure rm_rf can remove read-only directories (#5524)"""
+        from _pytest.pathlib import rm_rf
+
+        adir = tmp_path / "dir"
+        adir.mkdir()
+
+        (adir / "foo.txt").touch()
+        self.chmod_r(adir)
+
+        rm_rf(adir)
+
+        assert not adir.is_dir()
+
+    def test_on_rm_rf_error(self, tmp_path):
+        from _pytest.pathlib import on_rm_rf_error
+
+        adir = tmp_path / "dir"
+        adir.mkdir()
+
+        fn = adir / "foo.txt"
+        fn.touch()
+        self.chmod_r(fn)
+
+        # unknown exception
+        with pytest.warns(pytest.PytestWarning):
+            exc_info = (None, RuntimeError(), None)
+            on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
+            assert fn.is_file()
+
+        permission_error = OSError()
+        permission_error.errno = errno.EACCES
+
+        # unknown function
+        with pytest.warns(pytest.PytestWarning):
+            exc_info = (None, permission_error, None)
+            on_rm_rf_error(None, str(fn), exc_info, start_path=tmp_path)
+            assert fn.is_file()
+
+        exc_info = (None, permission_error, None)
+        on_rm_rf_error(os.unlink, str(fn), exc_info, start_path=tmp_path)
+        assert not fn.is_file()
 
 
 def attempt_symlink_to(path, to_path):
@@ -358,3 +425,24 @@
 
 def test_tmpdir_equals_tmp_path(tmpdir, tmp_path):
     assert Path(tmpdir) == tmp_path
+
+
+def test_basetemp_with_read_only_files(testdir):
+    """Integration test for #5524"""
+    testdir.makepyfile(
+        """
+        import os
+        import stat
+
+        def test(tmp_path):
+            fn = tmp_path / 'foo.txt'
+            fn.write_text(u'hello')
+            mode = os.stat(str(fn)).st_mode
+            os.chmod(str(fn), mode & ~stat.S_IREAD)
+    """
+    )
+    result = testdir.runpytest("--basetemp=tmp")
+    assert result.ret == 0
+    # running a second time and ensure we don't crash
+    result = testdir.runpytest("--basetemp=tmp")
+    assert result.ret == 0


Reply via email to