Skip to content

Commit a08e63f

Browse files
committed
Fix CI
1 parent ba9b81c commit a08e63f

2 files changed

Lines changed: 45 additions & 23 deletions

File tree

.github/workflows/ci.yml

Lines changed: 13 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -21,9 +21,9 @@ jobs:
2121
name: Lint
2222
runs-on: ubuntu-latest
2323
steps:
24-
- uses: actions/checkout@v6
24+
- uses: actions/checkout@v4
2525

26-
- uses: actions/setup-python@v6
26+
- uses: actions/setup-python@v5
2727
with:
2828
python-version: "3.12"
2929
cache: pip
@@ -52,13 +52,17 @@ jobs:
5252
python-version: "3.10"
5353

5454
steps:
55-
- uses: actions/checkout@v6
55+
- uses: actions/checkout@v4
5656

57-
- uses: actions/setup-python@v6
57+
- uses: actions/setup-python@v5
5858
with:
5959
python-version: ${{ matrix.python-version }}
6060
cache: pip
6161

62+
- name: Install libomp (macOS — required by XGBoost)
63+
if: runner.os == 'macOS'
64+
run: brew install libomp
65+
6266
- name: Install build tools + dev deps
6367
run: |
6468
python -m pip install --upgrade pip setuptools wheel
@@ -85,7 +89,7 @@ jobs:
8589

8690
- name: Upload test results
8791
if: always()
88-
uses: actions/upload-artifact@v6
92+
uses: actions/upload-artifact@v4
8993
with:
9094
name: test-results-${{ matrix.os }}-py${{ matrix.python-version }}
9195
path: test-results.xml
@@ -98,9 +102,9 @@ jobs:
98102
needs: lint
99103
runs-on: windows-latest
100104
steps:
101-
- uses: actions/checkout@v6
105+
- uses: actions/checkout@v4
102106

103-
- uses: actions/setup-python@v6
107+
- uses: actions/setup-python@v5
104108
with:
105109
python-version: "3.12"
106110

@@ -124,9 +128,9 @@ jobs:
124128
needs: test
125129
runs-on: ubuntu-latest
126130
steps:
127-
- uses: actions/checkout@v6
131+
- uses: actions/checkout@v4
128132

129-
- uses: actions/setup-python@v6
133+
- uses: actions/setup-python@v5
130134
with:
131135
python-version: "3.12"
132136

tests/test_new_modules.py

Lines changed: 32 additions & 14 deletions
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,43 @@
11
"""Tests for the new stats, multivariate, ML, DL, and validation modules."""
22
# ruff: noqa: E501
3+
import sys
34
import numpy as np
45
import pandas as pd
56
import pytest
67
from sklearn.datasets import make_classification
78
from sklearn.ensemble import RandomForestClassifier
89

910

11+
# ── Optional dependency availability (evaluated at collection time) ───────────
12+
13+
# torch
14+
try:
15+
import torch as _torch_check # noqa: F401
16+
_TORCH_AVAILABLE = True
17+
except ImportError:
18+
_TORCH_AVAILABLE = False
19+
20+
_skip_no_torch = pytest.mark.skipif(not _TORCH_AVAILABLE, reason="torch not installed")
21+
22+
# xgboost — instantiate XGBClassifier to force libxgboost.dylib load.
23+
# This catches the macOS libomp.dylib missing error at collection time
24+
# rather than letting the test crash at runtime.
25+
_XGB_SKIP_REASON: str = ""
26+
if sys.version_info >= (3, 14):
27+
_XGB_AVAILABLE = False
28+
_XGB_SKIP_REASON = "xgboost 3.x segfaults under CPython 3.14 (upstream C-API incompatibility)"
29+
else:
30+
try:
31+
from xgboost import XGBClassifier as _XGBCheck
32+
_XGBCheck() # forces dylib load → catches missing libomp on macOS
33+
_XGB_AVAILABLE = True
34+
except Exception as _e:
35+
_XGB_AVAILABLE = False
36+
_XGB_SKIP_REASON = f"xgboost not available: {_e}"
37+
38+
_skip_no_xgb = pytest.mark.skipif(not _XGB_AVAILABLE, reason=_XGB_SKIP_REASON)
39+
40+
1041
# ── shared fixtures ──────────────────────────────────────────────────────────
1142

1243
@pytest.fixture
@@ -343,12 +374,8 @@ def test_svm_fit(self, X_y_binary):
343374
clf = MLClassifier(X, y, model="svm", random_state=0).fit(cv=3)
344375
assert len(clf.predict(X)) == len(X)
345376

346-
@pytest.mark.skipif(
347-
__import__("sys").version_info >= (3, 14),
348-
reason="xgboost 3.x segfaults under CPython 3.14 (upstream C-API incompatibility)",
349-
)
377+
@_skip_no_xgb
350378
def test_xgb_fit(self, X_y_binary):
351-
pytest.importorskip("xgboost", reason="xgboost not installed")
352379
from metbit.ml.classifiers import MLClassifier
353380
X, y = X_y_binary
354381
clf = MLClassifier(X, y, model="xgb", random_state=0).fit(cv=3)
@@ -363,15 +390,6 @@ def test_elasticnet_fit(self, X_y_binary):
363390

364391
# ── dl/models ────────────────────────────────────────────────────────────────
365392

366-
try:
367-
import torch as _torch_check # noqa: F401
368-
_TORCH_AVAILABLE = True
369-
except ImportError:
370-
_TORCH_AVAILABLE = False
371-
372-
_skip_no_torch = pytest.mark.skipif(not _TORCH_AVAILABLE, reason="torch not installed")
373-
374-
375393
@_skip_no_torch
376394
class TestSpectralAutoencoder:
377395
def test_fit_encode(self, X_y_binary):

0 commit comments

Comments
 (0)