From 3f08781d0325691918a29f30f67b87aa71f22269 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:55:53 +0000 Subject: [PATCH 01/12] Initial plan From c552906fc1820a2bd06c9142919796d3970e29c9 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 11:57:51 +0000 Subject: [PATCH 02/12] Add pytest-xdist for parallel testing with -n auto Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- .github/workflows/ci-tests.yml | 2 +- requires_test.txt | 1 + 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 7373ac5a..7445869b 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -50,4 +50,4 @@ jobs: uv pip list - name: Run tests - run: pytest tests/ -v --disable-warnings --color=yes + run: pytest tests/ -v --disable-warnings --color=yes -n auto diff --git a/requires_test.txt b/requires_test.txt index 550bab9c..f3b71b4e 100644 --- a/requires_test.txt +++ b/requires_test.txt @@ -1,4 +1,5 @@ pytest ==8.3.2 +pytest-xdist ==3.6.1 mygene ==3.2.2 scvi-tools >=1.1.0, <1.3.0 From eab082435a3ed47d8498c318a0cc4a5c3a21160a Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 12:35:12 +0000 Subject: [PATCH 03/12] Add 30-minute timeout to CI test workflow Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- .github/workflows/ci-tests.yml | 1 + 1 file changed, 1 insertion(+) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 7445869b..5e81db20 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -18,6 +18,7 @@ concurrency: jobs: pytester: runs-on: ${{ matrix.os }} + timeout-minutes: 30 strategy: fail-fast: false matrix: From 38e80bc1586e7864a5a4c64c2905f5ce25c36404 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 14:03:18 +0000 Subject: [PATCH 04/12] Update concurrency group to use PR number or branch name Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- .github/workflows/ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index 5e81db20..e2d4ce7e 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -12,7 +12,7 @@ on: workflow_dispatch: concurrency: - group: ${{ github.workflow }}-${{ github.ref }} + group: ${{ github.workflow }}-${{ github.event.pull_request.number || github.ref_name }} cancel-in-progress: ${{ github.event_name == 'pull_request' }} jobs: From 52e645af36f0903a947ee7113a51e3d6e0f0ad64 Mon Sep 17 00:00:00 2001 From: Jirka Borovec <6035284+Borda@users.noreply.github.com> Date: Tue, 17 Feb 2026 15:21:43 +0100 Subject: [PATCH 05/12] Apply suggestion --- .github/workflows/ci-tests.yml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.github/workflows/ci-tests.yml b/.github/workflows/ci-tests.yml index e2d4ce7e..d06092cc 100644 --- a/.github/workflows/ci-tests.yml +++ b/.github/workflows/ci-tests.yml @@ -51,4 +51,4 @@ jobs: uv pip list - name: Run tests - run: pytest tests/ -v --disable-warnings --color=yes -n auto + run: pytest tests/ -v --color=yes -n 2 --dist=loadfile From 185382303bb8d00fbab51483165fcfd5e65e1d96 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:16:35 +0000 Subject: [PATCH 06/12] Add conftest.py to clean ./data and ./oracle before tests Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 37 +++++++++++++++++++++++++++++++++++++ 1 file changed, 37 insertions(+) create mode 100644 tests/conftest.py diff --git a/tests/conftest.py b/tests/conftest.py new file mode 100644 index 00000000..24e0d035 --- /dev/null +++ b/tests/conftest.py @@ -0,0 +1,37 @@ +# -*- coding: utf-8 -*- +""" +Pytest configuration and fixtures for TDC tests. + +This conftest.py ensures shared directories are cleaned before test execution +to prevent race conditions and shared state issues in parallel testing. +""" + +import os +import shutil + +import pytest + + +@pytest.fixture(scope="session", autouse=True) +def cleanup_shared_directories(): + """ + Clean up shared ./data and ./oracle directories before test session starts. + + This fixture runs automatically before any tests to ensure a clean state, + preventing race conditions when tests run in parallel with pytest-xdist. + """ + # Clean up before tests start + for directory in ["data", "oracle"]: + dir_path = os.path.join(os.getcwd(), directory) + if os.path.exists(dir_path): + shutil.rmtree(dir_path) + + # Let tests run + yield + + # Optional: Clean up after tests complete + # Commented out to allow inspection of test artifacts + # for directory in ["data", "oracle"]: + # dir_path = os.path.join(os.getcwd(), directory) + # if os.path.exists(dir_path): + # shutil.rmtree(dir_path) From 8428739c5c44a012ee69872e841c75ec660c96e4 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:17:49 +0000 Subject: [PATCH 07/12] Improve conftest.py with better error handling for parallel execution Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 27 ++++++++++++++++++++++----- 1 file changed, 22 insertions(+), 5 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 24e0d035..eb74b671 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,18 +13,31 @@ @pytest.fixture(scope="session", autouse=True) -def cleanup_shared_directories(): +def cleanup_shared_directories(tmp_path_factory): """ Clean up shared ./data and ./oracle directories before test session starts. This fixture runs automatically before any tests to ensure a clean state, preventing race conditions when tests run in parallel with pytest-xdist. + + With pytest-xdist, session-scoped fixtures run once per worker process, + but since all workers share the same working directory, we need to be + careful about race conditions. The --dist=loadfile strategy helps by + grouping tests by file to the same worker. """ + # Get the root directory where tests are run from + root_dir = os.getcwd() + # Clean up before tests start for directory in ["data", "oracle"]: - dir_path = os.path.join(os.getcwd(), directory) + dir_path = os.path.join(root_dir, directory) if os.path.exists(dir_path): - shutil.rmtree(dir_path) + try: + shutil.rmtree(dir_path) + except (OSError, FileNotFoundError): + # Directory might have been removed by another worker or doesn't exist + # This is okay, we just want to ensure it's clean + pass # Let tests run yield @@ -32,6 +45,10 @@ def cleanup_shared_directories(): # Optional: Clean up after tests complete # Commented out to allow inspection of test artifacts # for directory in ["data", "oracle"]: - # dir_path = os.path.join(os.getcwd(), directory) + # dir_path = os.path.join(root_dir, directory) # if os.path.exists(dir_path): - # shutil.rmtree(dir_path) + # try: + # shutil.rmtree(dir_path) + # except (OSError, FileNotFoundError): + # pass + From 2d6326ff773412fbc730f53097c93ed36e4b28ac Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:18:24 +0000 Subject: [PATCH 08/12] Remove unused tmp_path_factory parameter from fixture Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index eb74b671..607179de 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -13,7 +13,7 @@ @pytest.fixture(scope="session", autouse=True) -def cleanup_shared_directories(tmp_path_factory): +def cleanup_shared_directories(): """ Clean up shared ./data and ./oracle directories before test session starts. From f3e141de236feea33de6d8c49470909b94361cb6 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:18:56 +0000 Subject: [PATCH 09/12] Remove trailing blank line from conftest.py Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 1 - 1 file changed, 1 deletion(-) diff --git a/tests/conftest.py b/tests/conftest.py index 607179de..f0f4d231 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -51,4 +51,3 @@ def cleanup_shared_directories(): # shutil.rmtree(dir_path) # except (OSError, FileNotFoundError): # pass - From 87918cab41ab0bc253cf290686f8d63285312383 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:19:49 +0000 Subject: [PATCH 10/12] Fix whitespace and improve exception handling in conftest.py Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index f0f4d231..1c5c4d27 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -16,10 +16,10 @@ def cleanup_shared_directories(): """ Clean up shared ./data and ./oracle directories before test session starts. - + This fixture runs automatically before any tests to ensure a clean state, preventing race conditions when tests run in parallel with pytest-xdist. - + With pytest-xdist, session-scoped fixtures run once per worker process, but since all workers share the same working directory, we need to be careful about race conditions. The --dist=loadfile strategy helps by @@ -27,21 +27,21 @@ def cleanup_shared_directories(): """ # Get the root directory where tests are run from root_dir = os.getcwd() - + # Clean up before tests start for directory in ["data", "oracle"]: dir_path = os.path.join(root_dir, directory) if os.path.exists(dir_path): try: shutil.rmtree(dir_path) - except (OSError, FileNotFoundError): - # Directory might have been removed by another worker or doesn't exist + except FileNotFoundError: + # Directory was removed by another worker between check and removal # This is okay, we just want to ensure it's clean pass - + # Let tests run yield - + # Optional: Clean up after tests complete # Commented out to allow inspection of test artifacts # for directory in ["data", "oracle"]: @@ -49,5 +49,5 @@ def cleanup_shared_directories(): # if os.path.exists(dir_path): # try: # shutil.rmtree(dir_path) - # except (OSError, FileNotFoundError): + # except FileNotFoundError: # pass From 1a99752e298021bba34a190d2c287fc7f072c987 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:35:44 +0000 Subject: [PATCH 11/12] Use contextlib.suppress instead of try/except in conftest.py Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 1c5c4d27..75b5995b 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -8,6 +8,7 @@ import os import shutil +from contextlib import suppress import pytest @@ -32,12 +33,8 @@ def cleanup_shared_directories(): for directory in ["data", "oracle"]: dir_path = os.path.join(root_dir, directory) if os.path.exists(dir_path): - try: + with suppress(FileNotFoundError): shutil.rmtree(dir_path) - except FileNotFoundError: - # Directory was removed by another worker between check and removal - # This is okay, we just want to ensure it's clean - pass # Let tests run yield @@ -47,7 +44,5 @@ def cleanup_shared_directories(): # for directory in ["data", "oracle"]: # dir_path = os.path.join(root_dir, directory) # if os.path.exists(dir_path): - # try: + # with suppress(FileNotFoundError): # shutil.rmtree(dir_path) - # except FileNotFoundError: - # pass From c6d21d7707831287af85696e65e6d6b4be7b9c97 Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Tue, 17 Feb 2026 16:36:34 +0000 Subject: [PATCH 12/12] Remove redundant os.path.exists check to avoid TOCTOU issue Co-authored-by: Borda <6035284+Borda@users.noreply.github.com> --- tests/conftest.py | 10 ++++------ 1 file changed, 4 insertions(+), 6 deletions(-) diff --git a/tests/conftest.py b/tests/conftest.py index 75b5995b..801594e8 100644 --- a/tests/conftest.py +++ b/tests/conftest.py @@ -32,9 +32,8 @@ def cleanup_shared_directories(): # Clean up before tests start for directory in ["data", "oracle"]: dir_path = os.path.join(root_dir, directory) - if os.path.exists(dir_path): - with suppress(FileNotFoundError): - shutil.rmtree(dir_path) + with suppress(FileNotFoundError): + shutil.rmtree(dir_path) # Let tests run yield @@ -43,6 +42,5 @@ def cleanup_shared_directories(): # Commented out to allow inspection of test artifacts # for directory in ["data", "oracle"]: # dir_path = os.path.join(root_dir, directory) - # if os.path.exists(dir_path): - # with suppress(FileNotFoundError): - # shutil.rmtree(dir_path) + # with suppress(FileNotFoundError): + # shutil.rmtree(dir_path)