Skip to content

Commit cbd38fa

Browse files
committed
ci, ruff: add timeout (closes #30), separate linting, factor strategy/setup + fix lint
Signed-off-by: Élie Goudout <[email protected]>
1 parent f4f002d commit cbd38fa

File tree

9 files changed

+27
-31
lines changed

9 files changed

+27
-31
lines changed

.github/workflows/ci.yml

Lines changed: 14 additions & 18 deletions
Original file line numberDiff line numberDiff line change
@@ -7,23 +7,21 @@ on:
77
branches: [develop, release]
88

99
jobs:
10-
build:
11-
name: continuous-integration
12-
runs-on: ${{ matrix.os }}
10+
ci:
11+
timeout-minutes: 15
1312
strategy:
1413
matrix:
14+
os: ["ubuntu-latest", "windows-latest"] # Remove MacOS (billing + github.com/ThalesGroup/scio/issues/2)
1515
python-version: ["3.12", "3.13"]
16-
os: ["ubuntu-latest", "windows-latest", "macos-latest"]
17-
18-
16+
runs-on: ${{ matrix.os }}
1917
steps:
2018
- name: Checkout
2119
uses: actions/checkout@v4
2220

23-
- name: Install the latest version of uv and set the python version
21+
- name: Install uv and set python version
2422
uses: astral-sh/setup-uv@v6
2523
with:
26-
version: "0.8.9"
24+
version: "0.8.17"
2725
python-version: ${{ matrix.python-version }}
2826

2927
- name: Run ruff
@@ -35,8 +33,13 @@ jobs:
3533
run: |
3634
uv -v run mypy
3735
36+
- name: Build & Install
37+
run: |
38+
uv -v build
39+
uv -v pip install dist/scio_pypi-1.0.0rc3-py3-none-any.whl
40+
3841
- name: Build docs (Posix)
39-
if: matrix.os != 'windows-latest' && matrix.os != 'macos-latest' # Temporary (github.com/ThalesGroup/scio/issues/2)
42+
if: matrix.os != 'windows-latest'
4043
env:
4144
SPHINXOPTS: --fail-on-warning
4245
run: |
@@ -49,13 +52,7 @@ jobs:
4952
run: |
5053
uv -v run cmd /c "docs\\make.bat"
5154
52-
- name: Build & Install
53-
run: |
54-
uv -v build
55-
uv -v pip install dist/scio_pypi-1.0.0rc3-py3-none-any.whl
56-
5755
- name: Run pytest
58-
if: matrix.os != 'macos-latest' # Temporary (github.com/ThalesGroup/scio/issues/2)
5956
id: run-pytest
6057
continue-on-error: true
6158
run: |
@@ -67,13 +64,13 @@ jobs:
6764
with:
6865
name: pytest-observed-${{ matrix.os }}-py${{ matrix.python-version }}
6966
path: test/expected/*/*.observed.*
70-
retention-days: 7
67+
retention-days: 30
7168

7269
- name: Fail the job if pytest failed
7370
if: ${{ steps.run-pytest.outcome == 'failure' }}
7471
run: exit 1
7572

76-
- name: Upload coverage report to Codecov (Ubuntu, python3.13)
73+
- name: Upload coverage report to Codecov
7774
if: matrix.os == 'ubuntu-latest' && matrix.python-version == '3.13'
7875
uses: codecov/codecov-action@v5
7976
with:
@@ -82,7 +79,6 @@ jobs:
8279

8380
# TEMPORARILY DISABLED (https://github.com/ThalesGroup/scio/issues/9)
8481
# - name: Run pytest with lowest resolution
85-
# if: matrix.os != 'macos-latest' # Temporary (github.com/ThalesGroup/scio/issues/2)
8682
# id: run-pytest-lowest
8783
# continue-on-error: true
8884
# run: |

scio/scores/classification/deepmahalanobis.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -300,7 +300,7 @@ def compute_precision(residues: Tensor) -> Tensor:
300300
if not precision.isfinite().all():
301301
raise torch.linalg.LinAlgError # pragma: no cover # noqa: TRY301
302302
except torch.linalg.LinAlgError:
303-
data_dim = residues.size(1)
303+
data_dim = residues.shape[1]
304304
return torch.full((data_dim, data_dim), torch.nan).to(residues)
305305

306306
return precision

scio/scores/classification/dknn.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -61,7 +61,7 @@ def _check_params(self, n_calib: int) -> None:
6161
def calibrate(self, calib_data: Tensor, calib_labels: Tensor) -> None:
6262
"""Calibrate the scoring algorithm with In-Distribution data."""
6363
self.calib_labels = calib_labels
64-
n_samples, n_classes = self.rnet(calib_data).shape # Records activations
64+
n_samples = len(self.rnet(calib_data)) # Records activations
6565
all_activations = self.activations()
6666
self.indexes = make_indexes(all_activations, metric=self.index_metric)
6767

scio/scores/classification/gram.py

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -135,7 +135,7 @@ def calibrate(self, calib_data: Tensor, calib_labels_true: Tensor) -> None:
135135
def get_conformity(self, inputs: Tensor) -> tuple[Tensor, Tensor]:
136136
"""Compute output and associated conformity at inference."""
137137
out = self.rnet(inputs) # Records activations
138-
n_samples, n_classes = out.shape
138+
n_classes = out.shape[1]
139139

140140
total_deviations = torch.zeros_like(out)
141141
for activations, low_high, expected_deviation in zip(
@@ -184,7 +184,7 @@ def layer_stats(self, activations: Tensor) -> Tensor:
184184
)
185185
raise ValueError(msg)
186186

187-
n_channels = activations.size(1) if ndim == 4 else 1 # noqa: PLR2004 (magic value 4)
187+
n_channels = activations.shape[1] if ndim == 4 else 1 # noqa: PLR2004 (magic value 4)
188188
per_channel = activations.shape[ndim // 2 :].numel()
189189
activations_3d = activations.reshape(len(activations), n_channels, per_channel)
190190

scio/scores/classification/isomax.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -60,7 +60,7 @@ def calibrate(self, calib_data: Tensor, calib_labels: Tensor) -> None:
6060
with torch.no_grad():
6161
logits = self.rnet(calib_data, dont_record=True)
6262

63-
n_classes = logits.size(1)
63+
n_classes = logits.shape[1]
6464
# Init at 0 like [IsoMax]
6565
self.prototypes = torch.zeros(
6666
n_classes,

scio/scores/classification/jtla.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ def calibrate(self, calib_data: Tensor, calib_labels: Tensor) -> None:
167167
all_activations = self.activations()
168168
self.calib_labels_true = calib_labels
169169
self.calib_labels_pred = out.argmax(1) if self.pred_conditional else None
170-
self.prepare_tests(all_activations, out.size(1))
170+
self.prepare_tests(all_activations, out.shape[1])
171171
# Next are tensors of shape (n_classes, n_calib_samples, n_layers) (or None)
172172
self.calib_tests_true, self.calib_tests_pred = self.run_tests(all_activations)
173173

@@ -410,7 +410,7 @@ def aggregate_layers(
410410

411411
# Special aK-LPE method
412412
if self.layer_aggregation_method == "lpe":
413-
n_calib = self.lpe_true_calib.size(1)
413+
n_calib = self.lpe_true_calib.shape[1]
414414
similarity_search = self.index_metric == "ip"
415415

416416
normed_true = self.lpe_normalizer(tests_true)
@@ -510,7 +510,7 @@ def slicer(n: int, mask: Tensor) -> Tensor:
510510
if only_consecutive:
511511
return mask.unfold(1, n, 1)
512512

513-
range_n_layers = torch.arange(mask.size(1)).to(device=device)
513+
range_n_layers = torch.arange(mask.shape[1]).to(device=device)
514514
combs = torch.combinations(range_n_layers, n)
515515
return mask[:, combs]
516516

scio/scores/classification/odds.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ def calibrate(self, calib_data: Tensor, calib_labels: Tensor) -> None:
6868
self.rng = torch.Generator(calib_data.device).manual_seed(self.rng_seed)
6969

7070
logits = self.rnet(calib_data, dont_record=True)
71-
n_samples, n_classes = logits.shape
71+
n_classes = logits.shape[1]
7272
self.g_stats_avg = torch.full(
7373
(n_classes,) * 2,
7474
torch.nan,

test/scio/eval/classification/roc/test_roc.py

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,13 +18,13 @@ def test_roc_trivial():
1818
@parametrize_bool("label")
1919
def test_roc_requires_positive_and_negative(label):
2020
"""Test that both positive and negative samples are required."""
21-
with pytest.raises(AssertionError, match="^$"):
21+
with pytest.raises(AssertionError, match=r"^$"):
2222
ROC([label], [0])
2323

2424

2525
def test_roc_rejects_nan():
2626
"""Test that ``nan`` are forbidden."""
27-
with pytest.raises(AssertionError, match="^$"):
27+
with pytest.raises(AssertionError, match=r"^$"):
2828
ROC([T, F], [0, np.nan])
2929

3030

@@ -34,7 +34,7 @@ def test_roc_allows_only_posinf(sign):
3434
if sign > 0:
3535
ROC([T, F], [0, I])
3636
else:
37-
with pytest.raises(AssertionError, match="^$"):
37+
with pytest.raises(AssertionError, match=r"^$"):
3838
ROC([T, F], [0, -I])
3939

4040

test/scio/scores/classification/base/test_base.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -24,7 +24,7 @@ def test_raises_on_unexpected_mode(monkeypatch_enum_new_member, score, test_data
2424

2525
def test_accepts_unique_conformity(score, class_aggregation, test_data):
2626
"""Check that the score can output one score only per sample."""
27-
out, conformity = score(test_data)
27+
conformity = score(test_data)[1]
2828
same_conformity_over_classes = (conformity == conformity[:, [0]]).all()
2929

3030
assert conformity.shape == (len(test_data), N_CLASSES)

0 commit comments

Comments
 (0)