Script 'mail_helper' called by obssrc
Hello community,

here is the log from the commit of package python-pytest-forked for 
openSUSE:Factory checked in at 2026-08-05 17:49:52
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-pytest-forked (Old)
 and      /work/SRC/openSUSE:Factory/.python-pytest-forked.new.16738 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++

Package is "python-pytest-forked"

Wed Aug  5 17:49:52 2026 rev:11 rq:1369619 version:1.6.0

Changes:
--------
--- 
/work/SRC/openSUSE:Factory/python-pytest-forked/python-pytest-forked.changes    
    2025-05-07 19:16:23.527023154 +0200
+++ 
/work/SRC/openSUSE:Factory/.python-pytest-forked.new.16738/python-pytest-forked.changes
     2026-08-05 17:50:45.706819240 +0200
@@ -1,0 +2,6 @@
+Wed Aug  5 04:11:46 UTC 2026 - Steve Kowalik <[email protected]>
+
+- Add patch switch-to-multiprocessing.patch:
+  * Use multiprocessing rather than py.process.ForkedFunc.
+
+-------------------------------------------------------------------

New:
----
  _scmsync.obsinfo
  build.specials.obscpio
  switch-to-multiprocessing.patch

----------(New B)----------
  New:
- Add patch switch-to-multiprocessing.patch:
  * Use multiprocessing rather than py.process.ForkedFunc.
----------(New E)----------

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

Other differences:
------------------
++++++ python-pytest-forked.spec ++++++
--- /var/tmp/diff_new_pack.1TBCSA/_old  2026-08-05 17:50:46.230837571 +0200
+++ /var/tmp/diff_new_pack.1TBCSA/_new  2026-08-05 17:50:46.234837711 +0200
@@ -24,15 +24,15 @@
 License:        MIT
 URL:            https://github.com/pytest-dev/pytest-forked
 Source:         
https://files.pythonhosted.org/packages/source/p/pytest-forked/pytest-forked-%{version}.tar.gz
+# PATCH-FIX-UPSTREAM Based on gh#pytest-dev/pytest-forked#103
+Patch0:         switch-to-multiprocessing.patch
 BuildRequires:  %{python_module pip}
 BuildRequires:  %{python_module pytest >= 3.10}
-BuildRequires:  %{python_module py}
 BuildRequires:  %{python_module setuptools_scm}
 BuildRequires:  %{python_module setuptools}
 BuildRequires:  %{python_module wheel}
 BuildRequires:  fdupes
 BuildRequires:  python-rpm-macros
-Requires:       python-py
 Requires:       python-pytest >= 3.10
 BuildArch:      noarch
 %python_subpackages
@@ -41,7 +41,7 @@
 Extraction of pytest-xdist --forked module used for running tests in forked 
subprocess
 
 %prep
-%setup -q -n pytest-forked-%{version}
+%autosetup -p1 -n pytest-forked-%{version}
 
 %build
 %pyproject_wheel

++++++ _scmsync.obsinfo ++++++
mtime: 1785903114
commit: a9373e506767a6f2472a2d2ea6039267f0334490e94b9cd1657f00cb6c37f0e5
url: https://src.opensuse.org/python-pytest/python-pytest-forked
revision: a9373e506767a6f2472a2d2ea6039267f0334490e94b9cd1657f00cb6c37f0e5
projectscmsync: https://src.opensuse.org/python-pytest/_ObsPrj.git

++++++ build.specials.obscpio ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn' 
'--exclude=.svnignore' old/.gitignore new/.gitignore
--- old/.gitignore      1970-01-01 01:00:00.000000000 +0100
+++ new/.gitignore      2026-08-05 06:11:54.000000000 +0200
@@ -0,0 +1 @@
+.osc

++++++ switch-to-multiprocessing.patch ++++++
>From c33e4e1efad870b3b9aa308e4ec8ac145884c83d Mon Sep 17 00:00:00 2001
From: Bharath Krishna <[email protected]>
Date: Sun, 24 May 2026 13:28:44 +0000
Subject: [PATCH] Refactor forked process handling and output capture

---
 src/pytest_forked/__init__.py | 154 ++++++++++++++++++++++++++++++----
 1 file changed, 137 insertions(+), 17 deletions(-)

Index: pytest-forked-1.6.0/src/pytest_forked/__init__.py
===================================================================
--- pytest-forked-1.6.0.orig/src/pytest_forked/__init__.py
+++ pytest-forked-1.6.0/src/pytest_forked/__init__.py
@@ -1,25 +1,24 @@
 import os
+import sys
 import warnings
-
-import py
+import tempfile
+import marshal
 import pytest
 from _pytest import runner
+import multiprocessing
 
 # we know this bit is bad, but we cant help it with the current pytest setup
 
-
 # copied from xdist remote
 def serialize_report(rep):
-    import py
-
     d = rep.__dict__.copy()
     if hasattr(rep.longrepr, "toterminal"):
         d["longrepr"] = str(rep.longrepr)
     else:
         d["longrepr"] = rep.longrepr
     for name in d:
-        if isinstance(d[name], py.path.local):
-            d[name] = str(d[name])
+        if isinstance(d[name], os.PathLike):
+            d[name] = os.fspath(d[name])
         elif name == "result":
             d[name] = None  # for now
     return d
@@ -55,13 +54,61 @@ def pytest_runtest_protocol(item):
         return True
 
 
+class _ForkedResult:
+    """Mimics py.process.ForkedFunc result object."""
+    def __init__(self):
+        self.retval = None
+        self.exitstatus = 0
+        self.signal = 0
+        self.out = ""
+        self.err = ""
+
+
+def _worker(runforked_fn, stdout_path, stderr_path, retval_path):
+    """
+    Child process entry point.
+    Redirects OS-level fds 1 and 2 to files before running the test,
+    so output is captured even if the process is killed by a signal.
+    """
+    EXITSTATUS_EXCEPTION = 3
+
+    # Redirect stdout/stderr at the OS fd level (survives hard crashes)
+    stdout_fd = os.open(stdout_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
+    stderr_fd = os.open(stderr_path, os.O_WRONLY | os.O_CREAT | os.O_TRUNC)
+    os.dup2(stdout_fd, 1)
+    os.dup2(stderr_fd, 2)
+    os.close(stdout_fd)
+    os.close(stderr_fd)
+
+    # redirect Python-level streams so print() etc. work
+    sys.stdout = open(stdout_path, "w", buffering=1)
+    sys.stderr = open(stderr_path, "w", buffering=1)
+
+    try:
+        retval = runforked_fn()
+        with open(retval_path, "wb") as f:
+            f.write(retval)
+    except KeyboardInterrupt:
+        os._exit(4)  # EXITSTATUS_TESTEXIT
+    except SystemExit as e:
+        code = e.code if e.code is not None else 0
+        os._exit(int(code))
+    except Exception:
+        os._exit(EXITSTATUS_EXCEPTION)
+    finally:
+        try:
+            sys.stdout.flush()
+            sys.stderr.flush()
+        except Exception:
+            pass
+
+    os._exit(0)
+
+
 def forked_run_report(item):
-    # for now, we run setup/teardown in the subprocess
-    # XXX optionally allow sharing of setup/teardown
     from _pytest.runner import runtestprotocol
 
     EXITSTATUS_TESTEXIT = 4
-    import marshal
 
     def runforked():
         try:
@@ -70,8 +117,56 @@ def forked_run_report(item):
             os._exit(EXITSTATUS_TESTEXIT)
         return marshal.dumps([serialize_report(x) for x in reports])
 
-    ff = py.process.ForkedFunc(runforked)
-    result = ff.waitfinish()
+    # Use temp files for stdout/stderr — captured at OS fd level, so they
+    # survive a SIGKILL/SIGTERM just like the original ForkedFunc did.
+    with tempfile.TemporaryDirectory() as tmpdir:
+        stdout_path = os.path.join(tmpdir, "stdout")
+        stderr_path = os.path.join(tmpdir, "stderr")
+        retval_path = os.path.join(tmpdir, "retval")
+
+        # Pre-create files so reads don't fail if child never writes
+        open(stdout_path, "w").close()
+        open(stderr_path, "w").close()
+
+        ctx = multiprocessing.get_context("fork")
+        proc = ctx.Process(
+            target=_worker,
+            args=(runforked, stdout_path, stderr_path, retval_path),
+        )
+        proc.start()
+        proc.join()
+
+        result = _ForkedResult()
+        result.exitstatus = proc.exitcode if proc.exitcode is not None else 0
+
+        # Decode signal number from exit code the same way waitpid does:
+        # multiprocessing sets exitcode = -signum for signal-killed children
+        if proc.exitcode is not None and proc.exitcode < 0:
+            result.signal = -proc.exitcode
+
+        # Read captured output — available even after a crash
+        try:
+            with open(stdout_path, "r") as f:
+                result.out = f.read()
+        except OSError:
+            result.out = ""
+
+        try:
+            with open(stderr_path, "r") as f:
+                result.err = f.read()
+        except OSError:
+            result.err = ""
+
+        # Read return value only if child exited cleanly (no signal, no error)
+        if result.signal == 0 and result.exitstatus == 0:
+            try:
+                with open(retval_path, "rb") as f:
+                    retval_data = f.read()
+                if retval_data:
+                    result.retval = retval_data
+            except OSError:
+                result.retval = None
+
     if result.retval is not None:
         report_dumps = marshal.loads(result.retval)
         return [runner.TestReport(**x) for x in report_dumps]
@@ -82,9 +177,18 @@ def forked_run_report(item):
 
 
 def report_process_crash(item, result):
-    from _pytest._code import getfslineno
+    # getfslineno returns -1 when called from the parent process on an item
+    # whose source is only resolvable in the child. Use the item's own
+    # location (nodeid path + fspath) which is always populated by pytest.
+    try:
+        from _pytest._code import getfslineno
+        path, lineno = getfslineno(item)
+        if lineno == -1:
+            raise ValueError("unresolvable")
+    except Exception:
+        path = getattr(item, "fspath", None) or item.nodeid.split("::")[0]
+        lineno = item.location[1] if item.location[1] is not None else 0
 
-    path, lineno = getfslineno(item)
     info = "%s:%s: running the test CRASHED with signal %d" % (
         path,
         lineno,
@@ -110,11 +214,16 @@ def report_process_crash(item, result):
         return rep
 
     rep.outcome = "skipped"
+
+    xfail_reason = xfail_marker.kwargs.get(
+        "reason",
+        xfail_marker.args[0] if xfail_marker.args else "",
+    )
     rep.wasxfail = (
         "reason: {xfail_reason}; "
         "pytest-forked reason: {crash_info}".format(
-            xfail_reason=xfail_marker.kwargs["reason"],
-            crash_info=info,
+            xfail_reason=xfail_reason,
+            crash_info=info_bare,
         )
     )
     warnings.warn(
Index: pytest-forked-1.6.0/setup.py
===================================================================
--- pytest-forked-1.6.0.orig/setup.py
+++ pytest-forked-1.6.0/setup.py
@@ -19,7 +19,7 @@ setup(
         ],
     },
     zip_safe=False,
-    install_requires=["py", "pytest>=3.10"],
+    install_requires=["pytest>=3.10"],
     setup_requires=["setuptools_scm"],
     python_requires=">=3.7",
     classifiers=[

Reply via email to