Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pytest for openSUSE:Factory 
checked in at 2023-11-08 22:16:42
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest (Old)
 and      /work/SRC/openSUSE:Factory/.python-pytest.new.17445 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pytest"

Wed Nov  8 22:16:42 2023 rev:82 rq:1123974 version:7.4.3

Changes:
--------
--- /work/SRC/openSUSE:Factory/python-pytest/python-pytest.changes      
2023-10-15 19:25:59.453548501 +0200
+++ /work/SRC/openSUSE:Factory/.python-pytest.new.17445/python-pytest.changes   
2023-11-08 22:16:54.505366893 +0100
@@ -1,0 +2,11 @@
+Tue Nov  7 12:01:50 UTC 2023 - Dirk Müller <dmuel...@suse.com>
+
+- update to 7.4.3:
+  * Markers are now considered in the
+    reverse mro order to ensure base  class markers are
+    considered first -- this resolves a regression.
+  * Fixed ``:=`` in asserts impacting unrelated test cases.
+  * Handled an edge case where :data:`sys.stderr` might already
+    be closed when :ref:`faulthandler` is tearing down.
+
+-------------------------------------------------------------------

Old:
----
  pytest-7.4.2.tar.gz

New:
----
  pytest-7.4.3.tar.gz

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

Other differences:
------------------
++++++ python-pytest.spec ++++++
--- /var/tmp/diff_new_pack.1kbbak/_old  2023-11-08 22:16:55.357398194 +0100
+++ /var/tmp/diff_new_pack.1kbbak/_new  2023-11-08 22:16:55.357398194 +0100
@@ -33,7 +33,7 @@
 
 %{?sle15_python_module_pythons}
 Name:           python-pytest%{psuffix}
-Version:        7.4.2
+Version:        7.4.3
 Release:        0
 Summary:        Simple powerful testing with Python
 License:        MIT

++++++ pytest-7.4.2.tar.gz -> pytest-7.4.3.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/.github/workflows/deploy.yml 
new/pytest-7.4.3/.github/workflows/deploy.yml
--- old/pytest-7.4.2/.github/workflows/deploy.yml       2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/.github/workflows/deploy.yml       2023-10-24 
21:07:09.000000000 +0200
@@ -36,8 +36,10 @@
     timeout-minutes: 30
     permissions:
       id-token: write
+      contents: write
     steps:
     - uses: actions/checkout@v3
+
     - name: Download Package
       uses: actions/download-artifact@v3
       with:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/.readthedocs.yml 
new/pytest-7.4.3/.readthedocs.yml
--- old/pytest-7.4.2/.readthedocs.yml   2023-09-07 20:43:41.000000000 +0200
+++ new/pytest-7.4.3/.readthedocs.yml   2023-10-24 21:07:09.000000000 +0200
@@ -9,6 +9,10 @@
        path: .
      - requirements: doc/en/requirements.txt
 
+sphinx:
+  configuration: doc/en/conf.py
+  fail_on_warning: true
+
 build:
   os: ubuntu-20.04
   tools:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/AUTHORS new/pytest-7.4.3/AUTHORS
--- old/pytest-7.4.2/AUTHORS    2023-09-07 20:43:41.000000000 +0200
+++ new/pytest-7.4.3/AUTHORS    2023-10-24 21:07:09.000000000 +0200
@@ -231,6 +231,7 @@
 Maik Figura
 Mandeep Bhutani
 Manuel Krebber
+Marc Mueller
 Marc Schlaich
 Marcelo Duarte Trevisani
 Marcin Bachry
@@ -336,6 +337,7 @@
 Seth Junot
 Shantanu Jain
 Shubham Adep
+Simon Blanchard
 Simon Gomizelj
 Simon Holesch
 Simon Kerr
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/PKG-INFO new/pytest-7.4.3/PKG-INFO
--- old/pytest-7.4.2/PKG-INFO   2023-09-07 20:44:07.151998800 +0200
+++ new/pytest-7.4.3/PKG-INFO   2023-10-24 21:07:28.929523500 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pytest
-Version: 7.4.2
+Version: 7.4.3
 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-7.4.2/RELEASING.rst 
new/pytest-7.4.3/RELEASING.rst
--- old/pytest-7.4.2/RELEASING.rst      2023-09-07 20:43:41.000000000 +0200
+++ new/pytest-7.4.3/RELEASING.rst      2023-10-24 21:07:09.000000000 +0200
@@ -134,7 +134,8 @@
 Both automatic and manual processes described above follow the same steps from 
this point onward.
 
 #. After all tests pass and the PR has been approved, trigger the ``deploy`` 
job
-   in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml.
+   in https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml, using 
the ``release-MAJOR.MINOR.PATCH`` branch
+   as source.
 
    This job will require approval from ``pytest-dev/core``, after which it 
will publish to PyPI
    and tag the repository.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/doc/en/announce/index.rst 
new/pytest-7.4.3/doc/en/announce/index.rst
--- old/pytest-7.4.2/doc/en/announce/index.rst  2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/doc/en/announce/index.rst  2023-10-24 21:07:09.000000000 
+0200
@@ -6,6 +6,7 @@
    :maxdepth: 2
 
 
+   release-7.4.3
    release-7.4.2
    release-7.4.1
    release-7.4.0
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/doc/en/announce/release-7.4.3.rst 
new/pytest-7.4.3/doc/en/announce/release-7.4.3.rst
--- old/pytest-7.4.2/doc/en/announce/release-7.4.3.rst  1970-01-01 
01:00:00.000000000 +0100
+++ new/pytest-7.4.3/doc/en/announce/release-7.4.3.rst  2023-10-24 
21:07:09.000000000 +0200
@@ -0,0 +1,19 @@
+pytest-7.4.3
+=======================================
+
+pytest 7.4.3 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/stable/changelog.html.
+
+Thanks to all of the contributors to this release:
+
+* Bruno Oliveira
+* Marc Mueller
+
+
+Happy testing,
+The pytest Development Team
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/doc/en/changelog.rst 
new/pytest-7.4.3/doc/en/changelog.rst
--- old/pytest-7.4.2/doc/en/changelog.rst       2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/doc/en/changelog.rst       2023-10-24 21:07:09.000000000 
+0200
@@ -28,6 +28,21 @@
 
 .. towncrier release notes start
 
+pytest 7.4.3 (2023-10-24)
+=========================
+
+Bug Fixes
+---------
+
+- `#10447 <https://github.com/pytest-dev/pytest/issues/10447>`_: Markers are 
now considered in the reverse mro order to ensure base  class markers are 
considered first -- this resolves a regression.
+
+
+- `#11239 <https://github.com/pytest-dev/pytest/issues/11239>`_: Fixed ``:=`` 
in asserts impacting unrelated test cases.
+
+
+- `#11439 <https://github.com/pytest-dev/pytest/issues/11439>`_: Handled an 
edge case where :data:`sys.stderr` might already be closed when 
:ref:`faulthandler` is tearing down.
+
+
 pytest 7.4.2 (2023-09-07)
 =========================
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/doc/en/getting-started.rst 
new/pytest-7.4.3/doc/en/getting-started.rst
--- old/pytest-7.4.2/doc/en/getting-started.rst 2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/doc/en/getting-started.rst 2023-10-24 21:07:09.000000000 
+0200
@@ -22,7 +22,7 @@
 .. code-block:: bash
 
     $ pytest --version
-    pytest 7.4.2
+    pytest 7.4.3
 
 .. _`simpletest`:
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/doc/en/reference/customize.rst 
new/pytest-7.4.3/doc/en/reference/customize.rst
--- old/pytest-7.4.2/doc/en/reference/customize.rst     2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/doc/en/reference/customize.rst     2023-10-24 
21:07:09.000000000 +0200
@@ -90,7 +90,7 @@
 setup.cfg
 ~~~~~~~~~
 
-``setup.cfg`` files are general purpose configuration files, used originally 
by :doc:`distutils <python:distutils/configfile>`, and can also be used to hold 
pytest configuration
+``setup.cfg`` files are general purpose configuration files, used originally 
by ``distutils`` (now deprecated) and `setuptools 
<https://setuptools.pypa.io/en/latest/userguide/declarative_config.html>`__, 
and can also be used to hold pytest configuration
 if they have a ``[tool:pytest]`` section.
 
 .. code-block:: ini
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/scripts/prepare-release-pr.py 
new/pytest-7.4.3/scripts/prepare-release-pr.py
--- old/pytest-7.4.2/scripts/prepare-release-pr.py      2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/scripts/prepare-release-pr.py      2023-10-24 
21:07:09.000000000 +0200
@@ -31,10 +31,16 @@
 SLUG = "pytest-dev/pytest"
 
 PR_BODY = """\
-Created automatically from manual trigger.
+Created by the [prepare release 
pr](https://github.com/pytest-dev/pytest/actions/workflows/prepare-release-pr.yml)
+workflow.
 
-Once all builds pass and it has been **approved** by one or more maintainers, 
the build
-can be released by pushing a tag `{version}` to this repository.
+Once all builds pass and it has been **approved** by one or more maintainers,
+start the 
[deploy](https://github.com/pytest-dev/pytest/actions/workflows/deploy.yml) 
workflow, using these parameters:
+
+* `Use workflow from`: `release-{version}`.
+* `Release version`: `{version}`.
+
+After the `deploy` workflow has been approved by a core maintainer, the 
package will be uploaded to PyPI automatically.
 """
 
 
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/_version.py 
new/pytest-7.4.3/src/_pytest/_version.py
--- old/pytest-7.4.2/src/_pytest/_version.py    2023-09-07 20:44:06.000000000 
+0200
+++ new/pytest-7.4.3/src/_pytest/_version.py    2023-10-24 21:07:28.000000000 
+0200
@@ -1,4 +1,16 @@
 # file generated by setuptools_scm
 # don't change, don't track in version control
-__version__ = version = '7.4.2'
-__version_tuple__ = version_tuple = (7, 4, 2)
+TYPE_CHECKING = False
+if TYPE_CHECKING:
+    from typing import Tuple, Union
+    VERSION_TUPLE = Tuple[Union[int, str], ...]
+else:
+    VERSION_TUPLE = object
+
+version: str
+__version__: str
+__version_tuple__: VERSION_TUPLE
+version_tuple: VERSION_TUPLE
+
+__version__ = version = '7.4.3'
+__version_tuple__ = version_tuple = (7, 4, 3)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/assertion/rewrite.py 
new/pytest-7.4.3/src/_pytest/assertion/rewrite.py
--- old/pytest-7.4.2/src/_pytest/assertion/rewrite.py   2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/src/_pytest/assertion/rewrite.py   2023-10-24 
21:07:09.000000000 +0200
@@ -13,6 +13,7 @@
 import sys
 import tokenize
 import types
+from collections import defaultdict
 from pathlib import Path
 from pathlib import PurePath
 from typing import Callable
@@ -56,6 +57,10 @@
     astNum = ast.Num
 
 
+class Sentinel:
+    pass
+
+
 assertstate_key = StashKey["AssertionState"]()
 
 # pytest caches rewritten pycs in pycache dirs
@@ -63,6 +68,9 @@
 PYC_EXT = ".py" + (__debug__ and "c" or "o")
 PYC_TAIL = "." + PYTEST_TAG + PYC_EXT
 
+# Special marker that denotes we have just left a scope definition
+_SCOPE_END_MARKER = Sentinel()
+
 
 class AssertionRewritingHook(importlib.abc.MetaPathFinder, 
importlib.abc.Loader):
     """PEP302/PEP451 import hook which rewrites asserts."""
@@ -645,6 +653,8 @@
        .push_format_context() and .pop_format_context() which allows
        to build another %-formatted string while already building one.
 
+    :scope: A tuple containing the current scope used for variables_overwrite.
+
     :variables_overwrite: A dict filled with references to variables
        that change value within an assert. This happens when a variable is
        reassigned with the walrus operator
@@ -666,7 +676,10 @@
         else:
             self.enable_assertion_pass_hook = False
         self.source = source
-        self.variables_overwrite: Dict[str, str] = {}
+        self.scope: tuple[ast.AST, ...] = ()
+        self.variables_overwrite: defaultdict[
+            tuple[ast.AST, ...], Dict[str, str]
+        ] = defaultdict(dict)
 
     def run(self, mod: ast.Module) -> None:
         """Find all assert statements in *mod* and rewrite them."""
@@ -732,9 +745,17 @@
         mod.body[pos:pos] = imports
 
         # Collect asserts.
-        nodes: List[ast.AST] = [mod]
+        self.scope = (mod,)
+        nodes: List[Union[ast.AST, Sentinel]] = [mod]
         while nodes:
             node = nodes.pop()
+            if isinstance(node, (ast.FunctionDef, ast.AsyncFunctionDef, 
ast.ClassDef)):
+                self.scope = tuple((*self.scope, node))
+                nodes.append(_SCOPE_END_MARKER)
+            if node == _SCOPE_END_MARKER:
+                self.scope = self.scope[:-1]
+                continue
+            assert isinstance(node, ast.AST)
             for name, field in ast.iter_fields(node):
                 if isinstance(field, list):
                     new: List[ast.AST] = []
@@ -1005,7 +1026,7 @@
                     ]
                 ):
                     pytest_temp = self.variable()
-                    self.variables_overwrite[
+                    self.variables_overwrite[self.scope][
                         v.left.target.id
                     ] = v.left  # type:ignore[assignment]
                     v.left.target.id = pytest_temp
@@ -1048,17 +1069,20 @@
         new_args = []
         new_kwargs = []
         for arg in call.args:
-            if isinstance(arg, ast.Name) and arg.id in 
self.variables_overwrite:
-                arg = self.variables_overwrite[arg.id]  # 
type:ignore[assignment]
+            if isinstance(arg, ast.Name) and arg.id in 
self.variables_overwrite.get(
+                self.scope, {}
+            ):
+                arg = self.variables_overwrite[self.scope][
+                    arg.id
+                ]  # type:ignore[assignment]
             res, expl = self.visit(arg)
             arg_expls.append(expl)
             new_args.append(res)
         for keyword in call.keywords:
-            if (
-                isinstance(keyword.value, ast.Name)
-                and keyword.value.id in self.variables_overwrite
-            ):
-                keyword.value = self.variables_overwrite[
+            if isinstance(
+                keyword.value, ast.Name
+            ) and keyword.value.id in self.variables_overwrite.get(self.scope, 
{}):
+                keyword.value = self.variables_overwrite[self.scope][
                     keyword.value.id
                 ]  # type:ignore[assignment]
             res, expl = self.visit(keyword.value)
@@ -1094,12 +1118,14 @@
     def visit_Compare(self, comp: ast.Compare) -> Tuple[ast.expr, str]:
         self.push_format_context()
         # We first check if we have overwritten a variable in the previous 
assert
-        if isinstance(comp.left, ast.Name) and comp.left.id in 
self.variables_overwrite:
-            comp.left = self.variables_overwrite[
+        if isinstance(
+            comp.left, ast.Name
+        ) and comp.left.id in self.variables_overwrite.get(self.scope, {}):
+            comp.left = self.variables_overwrite[self.scope][
                 comp.left.id
             ]  # type:ignore[assignment]
         if isinstance(comp.left, namedExpr):
-            self.variables_overwrite[
+            self.variables_overwrite[self.scope][
                 comp.left.target.id
             ] = comp.left  # type:ignore[assignment]
         left_res, left_expl = self.visit(comp.left)
@@ -1119,7 +1145,7 @@
                 and next_operand.target.id == left_res.id
             ):
                 next_operand.target.id = self.variable()
-                self.variables_overwrite[
+                self.variables_overwrite[self.scope][
                     left_res.id
                 ] = next_operand  # type:ignore[assignment]
             next_res, next_expl = self.visit(next_operand)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/compat.py 
new/pytest-7.4.3/src/_pytest/compat.py
--- old/pytest-7.4.2/src/_pytest/compat.py      2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/src/_pytest/compat.py      2023-10-24 21:07:09.000000000 
+0200
@@ -380,15 +380,24 @@
 
 
 def get_user_id() -> int | None:
-    """Return the current user id, or None if we cannot get it reliably on the 
current platform."""
-    # win32 does not have a getuid() function.
-    # On Emscripten, getuid() is a stub that always returns 0.
-    if sys.platform in ("win32", "emscripten"):
+    """Return the current process's real user id or None if it could not be
+    determined.
+
+    :return: The user id or None if it could not be determined.
+    """
+    # mypy follows the version and platform checking expectation of PEP 484:
+    # 
https://mypy.readthedocs.io/en/stable/common_issues.html?highlight=platform#python-version-and-system-platform-checks
+    # Containment checks are too complex for mypy v1.5.0 and cause failure.
+    if sys.platform == "win32" or sys.platform == "emscripten":
+        # win32 does not have a getuid() function.
+        # Emscripten has a return 0 stub.
         return None
-    # getuid shouldn't fail, but cpython defines such a case.
-    # Let's hope for the best.
-    uid = os.getuid()
-    return uid if uid != -1 else None
+    else:
+        # On other platforms, a return value of -1 is assumed to indicate that
+        # the current process's real user id could not be determined.
+        ERROR = -1
+        uid = os.getuid()
+        return uid if uid != ERROR else None
 
 
 # Perform exhaustiveness checking.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/faulthandler.py 
new/pytest-7.4.3/src/_pytest/faulthandler.py
--- old/pytest-7.4.2/src/_pytest/faulthandler.py        2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/src/_pytest/faulthandler.py        2023-10-24 
21:07:09.000000000 +0200
@@ -1,4 +1,3 @@
-import io
 import os
 import sys
 from typing import Generator
@@ -51,7 +50,7 @@
         if fileno == -1:
             raise AttributeError()
         return fileno
-    except (AttributeError, io.UnsupportedOperation):
+    except (AttributeError, ValueError):
         # pytest-xdist monkeypatches sys.stderr with an object that is not an 
actual file.
         # 
https://docs.python.org/3/library/faulthandler.html#issue-with-file-descriptors
         # This is potentially dangerous, but the best we can do.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/mark/structures.py 
new/pytest-7.4.3/src/_pytest/mark/structures.py
--- old/pytest-7.4.2/src/_pytest/mark/structures.py     2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/src/_pytest/mark/structures.py     2023-10-24 
21:07:09.000000000 +0200
@@ -373,7 +373,9 @@
         if not consider_mro:
             mark_lists = [obj.__dict__.get("pytestmark", [])]
         else:
-            mark_lists = [x.__dict__.get("pytestmark", []) for x in 
obj.__mro__]
+            mark_lists = [
+                x.__dict__.get("pytestmark", []) for x in reversed(obj.__mro__)
+            ]
         mark_list = []
         for item in mark_lists:
             if isinstance(item, list):
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/_pytest/pathlib.py 
new/pytest-7.4.3/src/_pytest/pathlib.py
--- old/pytest-7.4.2/src/_pytest/pathlib.py     2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/src/_pytest/pathlib.py     2023-10-24 21:07:09.000000000 
+0200
@@ -623,8 +623,9 @@
         # Use the parts for the relative path to the root path.
         path_parts = relative_path.parts
 
-    # Module name for packages do not contain the __init__ file.
-    if path_parts[-1] == "__init__":
+    # Module name for packages do not contain the __init__ file, unless
+    # the `__init__.py` file is at the root.
+    if len(path_parts) >= 2 and path_parts[-1] == "__init__":
         path_parts = path_parts[:-1]
 
     return ".".join(path_parts)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/src/pytest.egg-info/PKG-INFO 
new/pytest-7.4.3/src/pytest.egg-info/PKG-INFO
--- old/pytest-7.4.2/src/pytest.egg-info/PKG-INFO       2023-09-07 
20:44:06.000000000 +0200
+++ new/pytest-7.4.3/src/pytest.egg-info/PKG-INFO       2023-10-24 
21:07:28.000000000 +0200
@@ -1,6 +1,6 @@
 Metadata-Version: 2.1
 Name: pytest
-Version: 7.4.2
+Version: 7.4.3
 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-7.4.2/src/pytest.egg-info/SOURCES.txt 
new/pytest-7.4.3/src/pytest.egg-info/SOURCES.txt
--- old/pytest-7.4.2/src/pytest.egg-info/SOURCES.txt    2023-09-07 
20:44:07.000000000 +0200
+++ new/pytest-7.4.3/src/pytest.egg-info/SOURCES.txt    2023-10-24 
21:07:28.000000000 +0200
@@ -234,6 +234,7 @@
 doc/en/announce/release-7.4.0.rst
 doc/en/announce/release-7.4.1.rst
 doc/en/announce/release-7.4.2.rst
+doc/en/announce/release-7.4.3.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-7.4.2/testing/conftest.py 
new/pytest-7.4.3/testing/conftest.py
--- old/pytest-7.4.2/testing/conftest.py        2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/testing/conftest.py        2023-10-24 21:07:09.000000000 
+0200
@@ -21,6 +21,15 @@
             sys.settrace(orig_trace)
 
 
+@pytest.fixture(autouse=True)
+def set_column_width(monkeypatch: pytest.MonkeyPatch) -> None:
+    """
+    Force terminal width to 80: some tests check the formatting of --help, 
which is sensible
+    to terminal width.
+    """
+    monkeypatch.setenv("COLUMNS", "80")
+
+
 @pytest.hookimpl(hookwrapper=True, tryfirst=True)
 def pytest_collection_modifyitems(items):
     """Prefer faster tests.
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/testing/logging/test_fixture.py 
new/pytest-7.4.3/testing/logging/test_fixture.py
--- old/pytest-7.4.2/testing/logging/test_fixture.py    2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/testing/logging/test_fixture.py    2023-10-24 
21:07:09.000000000 +0200
@@ -1,5 +1,7 @@
 # mypy: disable-error-code="attr-defined"
+# mypy: disallow-untyped-defs
 import logging
+from typing import Iterator
 
 import pytest
 from _pytest.logging import caplog_records_key
@@ -9,8 +11,8 @@
 sublogger = logging.getLogger(__name__ + ".baz")
 
 
-@pytest.fixture
-def cleanup_disabled_logging():
+@pytest.fixture(autouse=True)
+def cleanup_disabled_logging() -> Iterator[None]:
     """Simple fixture that ensures that a test doesn't disable logging.
 
     This is necessary because ``logging.disable()`` is global, so a test 
disabling logging
@@ -27,7 +29,7 @@
     result.stdout.fnmatch_lines(["*caplog*"])
 
 
-def test_change_level(caplog):
+def test_change_level(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.debug("handler DEBUG level")
     logger.info("handler INFO level")
@@ -42,7 +44,7 @@
     assert "CRITICAL" in caplog.text
 
 
-def test_change_level_logging_disabled(caplog, cleanup_disabled_logging):
+def test_change_level_logging_disabled(caplog: pytest.LogCaptureFixture) -> 
None:
     logging.disable(logging.CRITICAL)
     assert logging.root.manager.disable == logging.CRITICAL
     caplog.set_level(logging.WARNING)
@@ -85,9 +87,7 @@
     result.stdout.no_fnmatch_line("*log from test2*")
 
 
-def test_change_disabled_level_undo(
-    pytester: Pytester, cleanup_disabled_logging
-) -> None:
+def test_change_disabled_level_undo(pytester: Pytester) -> None:
     """Ensure that '_force_enable_logging' in 'set_level' is undone after the 
end of the test.
 
     Tests the logging output themselves (affected by disabled logging level).
@@ -144,7 +144,7 @@
     result.assert_outcomes(passed=3)
 
 
-def test_with_statement(caplog):
+def test_with_statement(caplog: pytest.LogCaptureFixture) -> None:
     with caplog.at_level(logging.INFO):
         logger.debug("handler DEBUG level")
         logger.info("handler INFO level")
@@ -159,7 +159,7 @@
     assert "CRITICAL" in caplog.text
 
 
-def test_with_statement_logging_disabled(caplog, cleanup_disabled_logging):
+def test_with_statement_logging_disabled(caplog: pytest.LogCaptureFixture) -> 
None:
     logging.disable(logging.CRITICAL)
     assert logging.root.manager.disable == logging.CRITICAL
     with caplog.at_level(logging.WARNING):
@@ -198,8 +198,8 @@
     ],
 )
 def test_force_enable_logging_level_string(
-    caplog, cleanup_disabled_logging, level_str, expected_disable_level
-):
+    caplog: pytest.LogCaptureFixture, level_str: str, expected_disable_level: 
int
+) -> None:
     """Test _force_enable_logging using a level string.
 
     ``expected_disable_level`` is one level below ``level_str`` because the 
disabled log level
@@ -218,7 +218,7 @@
     assert test_logger.manager.disable == expected_disable_level
 
 
-def test_log_access(caplog):
+def test_log_access(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.info("boo %s", "arg")
     assert caplog.records[0].levelname == "INFO"
@@ -226,7 +226,7 @@
     assert "boo arg" in caplog.text
 
 
-def test_messages(caplog):
+def test_messages(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.info("boo %s", "arg")
     logger.info("bar %s\nbaz %s", "arg1", "arg2")
@@ -247,14 +247,14 @@
     assert "Exception" not in caplog.messages[-1]
 
 
-def test_record_tuples(caplog):
+def test_record_tuples(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.info("boo %s", "arg")
 
     assert caplog.record_tuples == [(__name__, logging.INFO, "boo arg")]
 
 
-def test_unicode(caplog):
+def test_unicode(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.info("bū")
     assert caplog.records[0].levelname == "INFO"
@@ -262,7 +262,7 @@
     assert "bū" in caplog.text
 
 
-def test_clear(caplog):
+def test_clear(caplog: pytest.LogCaptureFixture) -> None:
     caplog.set_level(logging.INFO)
     logger.info("bū")
     assert len(caplog.records)
@@ -273,7 +273,9 @@
 
 
 @pytest.fixture
-def logging_during_setup_and_teardown(caplog):
+def logging_during_setup_and_teardown(
+    caplog: pytest.LogCaptureFixture,
+) -> Iterator[None]:
     caplog.set_level("INFO")
     logger.info("a_setup_log")
     yield
@@ -281,7 +283,9 @@
     assert [x.message for x in caplog.get_records("teardown")] == 
["a_teardown_log"]
 
 
-def test_caplog_captures_for_all_stages(caplog, 
logging_during_setup_and_teardown):
+def test_caplog_captures_for_all_stages(
+    caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None
+) -> None:
     assert not caplog.records
     assert not caplog.get_records("call")
     logger.info("a_call_log")
@@ -290,25 +294,31 @@
     assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
 
     # This reaches into private API, don't use this type of thing in real 
tests!
-    assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
+    caplog_records = caplog._item.stash[caplog_records_key]
+    assert set(caplog_records) == {"setup", "call"}
 
 
-def test_clear_for_call_stage(caplog, logging_during_setup_and_teardown):
+def test_clear_for_call_stage(
+    caplog: pytest.LogCaptureFixture, logging_during_setup_and_teardown: None
+) -> None:
     logger.info("a_call_log")
     assert [x.message for x in caplog.get_records("call")] == ["a_call_log"]
     assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
-    assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
+    caplog_records = caplog._item.stash[caplog_records_key]
+    assert set(caplog_records) == {"setup", "call"}
 
     caplog.clear()
 
     assert caplog.get_records("call") == []
     assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
-    assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
+    caplog_records = caplog._item.stash[caplog_records_key]
+    assert set(caplog_records) == {"setup", "call"}
 
     logging.info("a_call_log_after_clear")
     assert [x.message for x in caplog.get_records("call")] == 
["a_call_log_after_clear"]
     assert [x.message for x in caplog.get_records("setup")] == ["a_setup_log"]
-    assert set(caplog._item.stash[caplog_records_key]) == {"setup", "call"}
+    caplog_records = caplog._item.stash[caplog_records_key]
+    assert set(caplog_records) == {"setup", "call"}
 
 
 def test_ini_controls_global_log_level(pytester: Pytester) -> None:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/testing/test_assertrewrite.py 
new/pytest-7.4.3/testing/test_assertrewrite.py
--- old/pytest-7.4.2/testing/test_assertrewrite.py      2023-09-07 
20:43:41.000000000 +0200
+++ new/pytest-7.4.3/testing/test_assertrewrite.py      2023-10-24 
21:07:09.000000000 +0200
@@ -1531,6 +1531,28 @@
         result.stdout.fnmatch_lines(["*assert 4 > 5", "*where 5 = add_one(4)"])
 
 
+class TestIssue11239:
+    @pytest.mark.skipif(sys.version_info[:2] <= (3, 7), reason="Only Python 
3.8+")
+    def test_assertion_walrus_different_test_cases(self, pytester: Pytester) 
-> None:
+        """Regression for (#11239)
+
+        Walrus operator rewriting would leak to separate test cases if they 
used the same variables.
+        """
+        pytester.makepyfile(
+            """
+            def test_1():
+                state = {"x": 2}.get("x")
+                assert state is not None
+
+            def test_2():
+                db = {"x": 2}
+                assert (state := db.get("x")) is not None
+        """
+        )
+        result = pytester.runpytest()
+        assert result.ret == 0
+
+
 @pytest.mark.skipif(
     sys.maxsize <= (2**31 - 1), reason="Causes OverflowError on 32bit systems"
 )
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/testing/test_mark.py 
new/pytest-7.4.3/testing/test_mark.py
--- old/pytest-7.4.2/testing/test_mark.py       2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/testing/test_mark.py       2023-10-24 21:07:09.000000000 
+0200
@@ -1130,6 +1130,41 @@
 
     all_marks = get_unpacked_marks(C)
 
-    assert all_marks == [xfail("c").mark, xfail("a").mark, xfail("b").mark]
+    assert all_marks == [xfail("b").mark, xfail("a").mark, xfail("c").mark]
 
     assert get_unpacked_marks(C, consider_mro=False) == [xfail("c").mark]
+
+
+# @pytest.mark.issue("https://github.com/pytest-dev/pytest/issues/10447";)
+def test_mark_fixture_order_mro(pytester: Pytester):
+    """This ensures we walk marks of the mro starting with the base classes
+    the action at a distance fixtures are taken as minimal example from a real 
project
+
+    """
+    foo = pytester.makepyfile(
+        """
+        import pytest
+
+        @pytest.fixture
+        def add_attr1(request):
+            request.instance.attr1 = object()
+
+
+        @pytest.fixture
+        def add_attr2(request):
+            request.instance.attr2 = request.instance.attr1
+
+
+        @pytest.mark.usefixtures('add_attr1')
+        class Parent:
+            pass
+
+
+        @pytest.mark.usefixtures('add_attr2')
+        class TestThings(Parent):
+            def test_attrs(self):
+                assert self.attr1 == self.attr2
+        """
+    )
+    result = pytester.runpytest(foo)
+    result.assert_outcomes(passed=1)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/testing/test_parseopt.py 
new/pytest-7.4.3/testing/test_parseopt.py
--- old/pytest-7.4.2/testing/test_parseopt.py   2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/testing/test_parseopt.py   2023-10-24 21:07:09.000000000 
+0200
@@ -291,7 +291,8 @@
 
 def test_argcomplete(pytester: Pytester, monkeypatch: MonkeyPatch) -> None:
     try:
-        encoding = locale.getencoding()  # New in Python 3.11, ignores utf-8 
mode
+        # New in Python 3.11, ignores utf-8 mode
+        encoding = locale.getencoding()  # type: ignore[attr-defined]
     except AttributeError:
         encoding = locale.getpreferredencoding(False)
     try:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/pytest-7.4.2/testing/test_pathlib.py 
new/pytest-7.4.3/testing/test_pathlib.py
--- old/pytest-7.4.2/testing/test_pathlib.py    2023-09-07 20:43:41.000000000 
+0200
+++ new/pytest-7.4.3/testing/test_pathlib.py    2023-10-24 21:07:09.000000000 
+0200
@@ -28,6 +28,7 @@
 from _pytest.pathlib import safe_exists
 from _pytest.pathlib import symlink_or_skip
 from _pytest.pathlib import visit
+from _pytest.pytester import Pytester
 from _pytest.tmpdir import TempPathFactory
 
 
@@ -592,6 +593,10 @@
         result = module_name_from_path(tmp_path / "src/app/__init__.py", 
tmp_path)
         assert result == "src.app"
 
+        # Unless __init__.py file is at the root, in which case we cannot have 
an empty module name.
+        result = module_name_from_path(tmp_path / "__init__.py", tmp_path)
+        assert result == "__init__"
+
     def test_insert_missing_modules(
         self, monkeypatch: MonkeyPatch, tmp_path: Path
     ) -> None:
@@ -663,6 +668,22 @@
         mod = import_path(init, root=tmp_path, mode=ImportMode.importlib)
         assert len(mod.instance.INSTANCES) == 1
 
+    def test_importlib_root_is_package(self, pytester: Pytester) -> None:
+        """
+        Regression for importing a `__init__`.py file that is at the root
+        (#11417).
+        """
+        pytester.makepyfile(__init__="")
+        pytester.makepyfile(
+            """
+            def test_my_test():
+                assert True
+            """
+        )
+
+        result = pytester.runpytest("--import-mode=importlib")
+        result.stdout.fnmatch_lines("* 1 passed *")
+
 
 def test_safe_exists(tmp_path: Path) -> None:
     d = tmp_path.joinpath("some_dir")

Reply via email to