From e41434744e6c1d09f2904d50f354767557976c70 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 21:58:44 +0000 Subject: [PATCH 1/6] Initial plan From c44d10b93ed72f087fcfc70d90e292c90ae3fac2 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Thu, 2 Jul 2026 22:00:50 +0000 Subject: [PATCH 2/6] Reorder pr-check.yml so specific pytest version installs after test-requirements --- .github/workflows/pr-check.yml | 25 +++++++++++++------------ 1 file changed, 13 insertions(+), 12 deletions(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index c58844bbf110..846e461b5e46 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -172,18 +172,6 @@ jobs: with: python-version: ${{ matrix.python }} - - name: Install specific pytest version - if: matrix.pytest-version == 'pytest@pre-release' - run: | - python -m pip install --pre pytest - - - name: Install specific pytest version - if: matrix.pytest-version != 'pytest@pre-release' - run: | - python -m pip install "${{ matrix.pytest-version }}" - - - name: Install specific pytest version - run: python -m pytest --version - name: Install base Python requirements uses: brettcannon/pip-secure-install@92f400e3191171c1858cc0e0d9ac6320173fdb0c # v1.0.0 with: @@ -193,6 +181,19 @@ jobs: - name: Install test requirements run: python -m pip install --upgrade -r build/test-requirements.txt + # Install the specific pytest version AFTER test-requirements.txt so it is not + # overridden by the `pytest<8.1` pin (needed for pytest-black compatibility). + - name: Install specific pytest version (pre-release) + if: matrix.pytest-version == 'pytest@pre-release' + run: python -m pip install --upgrade --pre pytest + + - name: Install specific pytest version + if: matrix.pytest-version != 'pytest@pre-release' + run: python -m pip install --upgrade "${{ matrix.pytest-version }}" + + - name: Print pytest version + run: python -m pytest --version + - name: Run Python unit tests run: python python_files/tests/run_all.py From a903338a1a7077be8df01b0be409de49e9d472f5 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:24:41 +0000 Subject: [PATCH 3/6] Fix failing Python Tests CI job by preserving pytest<8.1 pin for pytest-black compatibility --- .github/workflows/pr-check.yml | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 846e461b5e46..74bf826b4633 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -183,12 +183,14 @@ jobs: # Install the specific pytest version AFTER test-requirements.txt so it is not # overridden by the `pytest<8.1` pin (needed for pytest-black compatibility). + # When pytest-version is 'pytest' (latest stable), keep the pinned version from + # test-requirements.txt to maintain pytest-black compatibility. - name: Install specific pytest version (pre-release) if: matrix.pytest-version == 'pytest@pre-release' run: python -m pip install --upgrade --pre pytest - name: Install specific pytest version - if: matrix.pytest-version != 'pytest@pre-release' + if: matrix.pytest-version != 'pytest@pre-release' && matrix.pytest-version != 'pytest' run: python -m pip install --upgrade "${{ matrix.pytest-version }}" - name: Print pytest version From cdb5ddf167cadb11411ddfc20c10c62c07388e35 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:34:48 +0000 Subject: [PATCH 4/6] Replace pytest-black with local conftest; remove pytest<8.1 pin --- .github/workflows/pr-check.yml | 6 +- build/test-requirements.txt | 4 - .../.data/2496-black-formatter/conftest.py | 149 ++++++++++++++++++ 3 files changed, 150 insertions(+), 9 deletions(-) create mode 100644 python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index 74bf826b4633..af92b255ae5b 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -181,16 +181,12 @@ jobs: - name: Install test requirements run: python -m pip install --upgrade -r build/test-requirements.txt - # Install the specific pytest version AFTER test-requirements.txt so it is not - # overridden by the `pytest<8.1` pin (needed for pytest-black compatibility). - # When pytest-version is 'pytest' (latest stable), keep the pinned version from - # test-requirements.txt to maintain pytest-black compatibility. - name: Install specific pytest version (pre-release) if: matrix.pytest-version == 'pytest@pre-release' run: python -m pip install --upgrade --pre pytest - name: Install specific pytest version - if: matrix.pytest-version != 'pytest@pre-release' && matrix.pytest-version != 'pytest' + if: matrix.pytest-version != 'pytest@pre-release' run: python -m pip install --upgrade "${{ matrix.pytest-version }}" - name: Print pytest version diff --git a/build/test-requirements.txt b/build/test-requirements.txt index d1acb9a33d84..f19194c2c772 100644 --- a/build/test-requirements.txt +++ b/build/test-requirements.txt @@ -7,9 +7,6 @@ pylint pycodestyle pydocstyle prospector -# pytest-black 0.6.0 uses the deprecated `path` arg in pytest_collect_file, -# which was removed in pytest 8.1. Pin to <8.1 to maintain compatibility. -pytest<8.1 flask fastapi uvicorn @@ -41,4 +38,3 @@ pytest-describe # for pytest-ruff related tests pytest-ruff -pytest-black diff --git a/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py b/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py new file mode 100644 index 000000000000..30af91f89fd5 --- /dev/null +++ b/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py @@ -0,0 +1,149 @@ +# -*- coding: utf-8 -*- +# Local replacement for the pytest-black plugin that supports pytest 7+. +# pytest-black 0.6.0 uses the deprecated `path` argument in pytest_collect_file, +# which was removed in pytest 8.1. This conftest provides a compatible implementation. + +import re +import subprocess +import sys + +import pytest + +PYTEST_VER = tuple(int(x) for x in pytest.__version__.split(".")[:2]) + +try: + import tomllib +except ImportError: + try: + import tomli as tomllib # type: ignore[no-redef] + except ImportError: + tomllib = None # type: ignore[assignment] + +HISTKEY = "black/mtimes" + + +def pytest_addoption(parser): + group = parser.getgroup("general") + group.addoption( + "--black", action="store_true", help="enable format checking with black" + ) + + +def pytest_configure(config): + # load cached mtimes at session startup + if config.option.black and hasattr(config, "cache"): + config._blackmtimes = config.cache.get(HISTKEY, {}) + config.addinivalue_line("markers", "black: enable format checking with black") + + +def pytest_unconfigure(config): + # save cached mtimes at end of session + if hasattr(config, "_blackmtimes"): + config.cache.set(HISTKEY, config._blackmtimes) + + +if PYTEST_VER >= (8, 1): + + def pytest_collect_file(file_path, parent): + config = parent.config + if ( + config.option.black + and file_path.suffix in (".py", ".pyi") + and file_path.name != "conftest.py" + ): + return BlackFile.from_parent(parent, path=file_path) + +elif PYTEST_VER >= (7, 0): + + def pytest_collect_file(file_path, path, parent): # type: ignore[misc] + config = parent.config + if ( + config.option.black + and file_path.suffix in (".py", ".pyi") + and file_path.name != "conftest.py" + ): + return BlackFile.from_parent(parent, path=file_path) + + +class BlackFile(pytest.File): + def collect(self): + """Return a list of children (items and collectors) for this collection node.""" + yield BlackItem.from_parent(self, name="black") + + +class BlackItem(pytest.Item): + def __init__(self, **kwargs): + super().__init__(**kwargs) + self.add_marker("black") + try: + if tomllib is not None: + with open("pyproject.toml", "rb") as toml_file: + settings = tomllib.load(toml_file)["tool"]["black"] + if "include" in settings: + settings["include"] = self._re_fix_verbose(settings["include"]) + if "exclude" in settings: + settings["exclude"] = self._re_fix_verbose(settings["exclude"]) + self.pyproject = settings + else: + self.pyproject = {} + except Exception: + self.pyproject = {} + + def setup(self): + pytest.importorskip("black") + mtimes = getattr(self.config, "_blackmtimes", {}) + self._blackmtime = self.path.stat().st_mtime + old = mtimes.get(str(self.path), 0) + if self._blackmtime == old: + pytest.skip("file(s) previously passed black format checks") + + if self._skip_test(): + pytest.skip("file(s) excluded by pyproject.toml") + + def runtest(self): + cmd = [ + sys.executable, + "-m", + "black", + "--check", + "--diff", + "--quiet", + str(self.path), + ] + try: + subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True) + except subprocess.CalledProcessError as e: + raise BlackError(e) + + mtimes = getattr(self.config, "_blackmtimes", {}) + mtimes[str(self.path)] = self._blackmtime + + def repr_failure(self, excinfo): + if excinfo.errisinstance(BlackError): + return excinfo.value.args[0].stdout + return super().repr_failure(excinfo) + + def reportinfo(self): + return (self.path, -1, "Black format check") + + def _skip_test(self): + return self._excluded() or (not self._included()) + + def _included(self): + if "include" not in self.pyproject: + return True + return re.search(self.pyproject["include"], str(self.path)) + + def _excluded(self): + if "exclude" not in self.pyproject: + return False + return re.search(self.pyproject["exclude"], str(self.path)) + + def _re_fix_verbose(self, regex): + if "\n" in regex: + regex = "(?x)" + regex + return re.compile(regex) + + +class BlackError(Exception): + pass From 43a5c240d0f756a23b3b57f877a37877e4380b7b Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 16:37:48 +0000 Subject: [PATCH 5/6] Use text=True in subprocess.run; document why path param must match hookspec --- .../pytestadapter/.data/2496-black-formatter/conftest.py | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py b/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py index 30af91f89fd5..ec7c872d690e 100644 --- a/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py +++ b/python_files/tests/pytestadapter/.data/2496-black-formatter/conftest.py @@ -55,7 +55,8 @@ def pytest_collect_file(file_path, parent): elif PYTEST_VER >= (7, 0): - def pytest_collect_file(file_path, path, parent): # type: ignore[misc] + def pytest_collect_file(file_path, path, parent): # type: ignore[misc] # noqa: ARG001 + # `path` must match the pytest 7.x hookspec; use file_path (pathlib.Path) in body. config = parent.config if ( config.option.black @@ -111,7 +112,7 @@ def runtest(self): str(self.path), ] try: - subprocess.run(cmd, check=True, stdout=subprocess.PIPE, universal_newlines=True) + subprocess.run(cmd, check=True, stdout=subprocess.PIPE, text=True) except subprocess.CalledProcessError as e: raise BlackError(e) From 12f414526d662224b021ea0039718bd5f859790c Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 17 Jul 2026 17:19:07 +0000 Subject: [PATCH 6/6] Fix pytest 6.2 CI lane plugin compatibility installs --- .github/workflows/pr-check.yml | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/.github/workflows/pr-check.yml b/.github/workflows/pr-check.yml index af92b255ae5b..7e215cdd813b 100644 --- a/.github/workflows/pr-check.yml +++ b/.github/workflows/pr-check.yml @@ -189,6 +189,11 @@ jobs: if: matrix.pytest-version != 'pytest@pre-release' run: python -m pip install --upgrade "${{ matrix.pytest-version }}" + - name: Install pytest plugin compatibility packages + if: matrix.pytest-version == 'pytest==6.2.0' + run: | + python -m pip install --upgrade "pytest-cov<6.2.1" "pytest-describe<3.2" "pytest-timeout<2.3.1" + - name: Print pytest version run: python -m pytest --version