From 4e7bd0239e136ef35d28e87838c0bc1b8b7c2189 Mon Sep 17 00:00:00 2001 From: Bruno Oliveira Date: Fri, 19 May 2023 07:43:18 -0300 Subject: [PATCH] Avoid unnecessary rinfo calls after creating gateways (#909) Hopefully this fixes #907, as seems this is the only change in #901 which is somehow related. --------- Co-authored-by: Ronny Pfannschmidt --- changelog/907.bugfix.rst | 5 +++++ src/xdist/dsession.py | 31 +++++++++++++++---------------- 2 files changed, 20 insertions(+), 16 deletions(-) create mode 100644 changelog/907.bugfix.rst diff --git a/changelog/907.bugfix.rst b/changelog/907.bugfix.rst new file mode 100644 index 0000000..e25bd48 --- /dev/null +++ b/changelog/907.bugfix.rst @@ -0,0 +1,5 @@ +Avoid remote calls during startup as ``execnet`` by default does not ensure remote affinity with the +main thread and might accidentally schedule the pytest worker into a non-main thread, which breaks numerous frameworks, +for example ``asyncio``, ``anyio``, ``PyQt/PySide``, etc. + +A more safe correction will require thread affinity in ``execnet`` (`pytest-dev/execnet#96 `__). diff --git a/src/xdist/dsession.py b/src/xdist/dsession.py index 908f270..39d1afa 100644 --- a/src/xdist/dsession.py +++ b/src/xdist/dsession.py @@ -444,26 +444,25 @@ class TerminalDistReporter: @pytest.hookimpl def pytest_xdist_newgateway(self, gateway) -> None: - rinfo = gateway._rinfo() - is_local = rinfo.executable == sys.executable - if self.config.option.verbose > 0 and not is_local: - version = "%s.%s.%s" % rinfo.version_info[:3] - self.rewrite( - "[%s] %s Python %s cwd: %s" - % (gateway.id, rinfo.platform, version, rinfo.cwd), - newline=True, - ) + if self.config.option.verbose > 0: + rinfo = gateway._rinfo() + different_interpreter = rinfo.executable != sys.executable + if different_interpreter: + version = "%s.%s.%s" % rinfo.version_info[:3] + self.rewrite( + f"[{gateway.id}] {rinfo.platform} Python {version} cwd: {rinfo.cwd}", + newline=True, + ) self.setstatus(gateway.spec, WorkerStatus.Initialized, tests_collected=0) @pytest.hookimpl def pytest_testnodeready(self, node) -> None: - d = node.workerinfo - is_local = d.get("executable") == sys.executable - if self.config.option.verbose > 0 and not is_local: - infoline = "[{}] Python {}".format( - d["id"], d["version"].replace("\n", " -- ") - ) - self.rewrite(infoline, newline=True) + if self.config.option.verbose > 0: + d = node.workerinfo + different_interpreter = d.get("executable") != sys.executable + if different_interpreter: + version = d["version"].replace("\n", " -- ") + self.rewrite(f"[{d['id']}] Python {version}", newline=True) self.setstatus( node.gateway.spec, WorkerStatus.ReadyForCollection, tests_collected=0 )