Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
54 changes: 45 additions & 9 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -29,17 +29,11 @@ jobs:

- name: Lint
run: |
uv run ruff check --exclude tests .
uv run ruff check .

- name: Format
run: |
uv run ruff format --check --exclude tests .

# Tests are temporarily disabled in CI until they are ready.
# To re-enable, uncomment the step below once tests are stable.
# - name: Run pytest
# run: |
# uv run pytest
uv run ruff format --check .

type-check:
name: Type Check
Expand All @@ -61,5 +55,47 @@ jobs:

- name: Type check
run: |
uv run ty check src
uv run ty check .

test:
name: Tests (${{ matrix.os }})
runs-on: ${{ matrix.os }}
strategy:
fail-fast: false
matrix:
include:
- os: ubuntu-latest
- os: windows-latest
# Apple Silicon (arm64); see https://github.com/actions/runner-images
- os: macos-14

steps:
- name: Checkout repository
uses: actions/checkout@v6

- name: Set up uv
uses: astral-sh/setup-uv@cec208311dfd045dd5311c1add060b2062131d57
with:
python-version: "3.14"
enable-cache: true

- name: Sync dependencies
run: |
uv sync --locked --dev

# PySide6 links libEGL even for offscreen; ubuntu-latest images omit it by default.
- name: Install Qt EGL/XCB dependencies (Ubuntu only)
if: matrix.os == 'ubuntu-latest'
run: |
sudo apt-get update
sudo apt-get install -y --no-install-recommends \
libegl1 \
libgl1 \
libxkbcommon0 \
libdbus-1-3

- name: Run pytest
env:
QT_QPA_PLATFORM: offscreen
run: |
uv run pytest --cov-fail-under=48
6 changes: 3 additions & 3 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -9,12 +9,12 @@ repos:
hooks:
- id: ruff-format
- id: ruff-check
args: ["--fix", "--exclude", "tests"]
args: ["--fix"]

- repo: local
hooks:
- id: ty-check
name: ty check (src)
entry: uv run ty check src
name: ty check
entry: uv run ty check .
language: system
pass_filenames: false
36 changes: 17 additions & 19 deletions pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -33,9 +33,9 @@ dependencies = [
dev = [
"pytest>=8.0.0",
"pytest-qt>=4.4.0",
"pytest-timeout>=2.3.0",
"pytest-cov>=4.1.0",
"ruff>=0.1.0",
# "mypy>=1.8.0",
"pre-commit>=3.6",
"ty>=0.0.30",
"pandas-stubs>=3.0.0.260204",
Expand Down Expand Up @@ -76,10 +76,26 @@ python_classes = ["Test*"]
python_functions = ["test_*"]
addopts = [
"--verbose",
"--timeout=3",
"--cov=dbs_annotator",
"--cov-report=html",
"--cov-report=term-missing",
]
filterwarnings = [
"ignore::DeprecationWarning",
]
markers = [
"gui: Qt GUI / widget tests",
"integration: cross-module behavior",
"slow: longer GUI or lazy-loaded wizard flows; skip locally with pytest -m \"not slow\"",
]

[tool.coverage.run]
source = ["src"]
omit = ["*/tests/*"]

[tool.coverage.report]
omit = ["*/tests/*"]

[tool.ruff]
line-length = 88
Expand Down Expand Up @@ -107,21 +123,3 @@ select = [
ignore = [
"E501", # line too long (handled by formatter/line-length)
]

[tool.mypy]
python_version = "3.11"
warn_return_any = true
warn_unused_configs = true
disallow_untyped_defs = false
disallow_incomplete_defs = false
check_untyped_defs = true
no_implicit_optional = true
warn_redundant_casts = true
warn_unused_ignores = true
warn_no_return = true
strict_optional = true

[[tool.mypy.overrides]]
module = "PySide6.*"
ignore_missing_imports = true

5 changes: 3 additions & 2 deletions src/dbs_annotator/utils/report_chart_utils.py
Original file line number Diff line number Diff line change
Expand Up @@ -54,9 +54,10 @@ def parse_scale_targets(
targets[name] = {"type": "max", "value": float(smax) if smax else 0.0}
elif mode == "custom":
try:
targets[name] = {"type": "custom", "value": float(custom_val)}
custom_num = float(custom_val)
except ValueError, TypeError:
targets[name] = {"type": "custom", "value": 0.0}
custom_num = 0.0
targets[name] = {"type": "custom", "value": custom_num}
return targets


Expand Down
29 changes: 29 additions & 0 deletions tests/conftest.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
"""Shared pytest fixtures for Qt and the main wizard."""

from __future__ import annotations

import os

# Headless-friendly Qt before any QWidget is constructed (pytest loads conftest early).
os.environ.setdefault("QT_QPA_PLATFORM", "offscreen")

import pytest

from dbs_annotator.views.wizard_window import WizardWindow


@pytest.fixture
def wizard(qtbot, qapp):
"""Main wizard window bound to the session QApplication."""
w = WizardWindow(qapp)
qtbot.addWidget(w)
w.show()
return w


@pytest.fixture
def bids_like_tsv(tmp_path):
"""Minimal TSV path suitable for SessionData.open_file (new file)."""
path = tmp_path / "sub-01_ses-20250101_task-prog_run-01_events.tsv"
path.write_text("", encoding="utf-8")
return path
Loading