Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
85 commits
Select commit Hold shift + click to select a range
fafe1a2
test(data): improve dataviewer backend coverage for OpenSSF Silver
WilliamBerryiii Apr 23, 2026
7a1e9ab
test(dataviewer): rework backend tests per Major findings IV-001..IV-005
WilliamBerryiii Apr 23, 2026
8a58bdf
test(extension): sweep utcnow warnings and fix flaky pre-existing tests
WilliamBerryiii Apr 23, 2026
5e17148
test(extension): expand dataviewer backend coverage for storage/blob_…
WilliamBerryiii Apr 24, 2026
793695e
test(extension): add unit tests for EpisodeClusterer service
WilliamBerryiii Apr 24, 2026
99dfa7a
test(extension): add unit tests for LeRobot dataset loader
WilliamBerryiii Apr 24, 2026
92b228e
test(extension): add unit tests for LeRobot dataset handler
WilliamBerryiii Apr 24, 2026
5996ce8
test(extension): add unit tests for YOLO detection service
WilliamBerryiii Apr 24, 2026
42a4ff5
test(extension): add unit tests for anomaly detection service
WilliamBerryiii Apr 24, 2026
9c615ac
test(extension): add unit tests for dataset service orchestrator
WilliamBerryiii Apr 24, 2026
efd9755
test(extension): add unit tests for joint config router
WilliamBerryiii Apr 24, 2026
5660cea
test(extension): add unit tests for ai analysis router
WilliamBerryiii Apr 24, 2026
b64ab7a
test(extension): add unit tests for export router
WilliamBerryiii Apr 24, 2026
14d494c
test(extension): add unit tests for datasets router
WilliamBerryiii Apr 24, 2026
ada997b
ops(workflows): wire evaluation-pytests into main.yml
WilliamBerryiii Apr 24, 2026
f5f9df8
test(extension): expand hdf5 handler tests for video and discovery br…
WilliamBerryiii Apr 25, 2026
b5c8c8c
test(extension): cover huggingface adapter branch and error paths
WilliamBerryiii Apr 25, 2026
cd4bbbd
test(extension): cover azure blob storage adapter error paths and man…
WilliamBerryiii Apr 25, 2026
2cf7e45
test(extension): cover image transform error paths and batch helpers
WilliamBerryiii Apr 25, 2026
1682200
test(extension): cover hdf5 loader read paths and discovery branches
WilliamBerryiii Apr 25, 2026
c7a7831
test(extension): cover api validation dependency factories and saniti…
WilliamBerryiii Apr 26, 2026
d613cbd
test(extension): cover analysis router stub endpoints
WilliamBerryiii Apr 26, 2026
29e26f1
test(extension): cover api config validation branches
WilliamBerryiii Apr 26, 2026
7840880
test(extension): cover detection model validator branches
WilliamBerryiii Apr 26, 2026
9db9c0c
test(extension): cover local storage error paths
WilliamBerryiii Apr 26, 2026
0129582
test(extension): cover middleware skip paths and body size enforcement
WilliamBerryiii Apr 26, 2026
1f704e0
test(extension): cover detection router endpoints
WilliamBerryiii Apr 26, 2026
87c1bc8
test(extension): cover annotation router endpoints
WilliamBerryiii Apr 26, 2026
8970940
test(extension): cover annotation service
WilliamBerryiii Apr 26, 2026
7a0e6be
test(extension): cover auth providers and dependencies
WilliamBerryiii Apr 26, 2026
6f4ab97
test(extension): cover storage adapter base contract
WilliamBerryiii Apr 26, 2026
308411b
test(extension): cover detection service end-to-end flow
WilliamBerryiii Apr 26, 2026
c6bcb6f
test(extension): cover labels router endpoints
WilliamBerryiii Apr 26, 2026
ed384a3
test(extension): repair tests/api async fixtures
WilliamBerryiii Apr 27, 2026
215b382
test(extension): convert async tests to sync via asyncio.run wrapper
WilliamBerryiii Apr 27, 2026
4ea60a0
test(evaluation): isolate upload-artifact discovery and enforce 80% c…
WilliamBerryiii Apr 27, 2026
e1226dd
test(training): add unit tests for shutdown, mlflow agent, lerobot bo…
WilliamBerryiii Apr 27, 2026
8e4bd22
test(training): add unit tests for lerobot checkpoints and train
WilliamBerryiii Apr 27, 2026
f254268
test(training): add unit tests for lerobot download_dataset
WilliamBerryiii Apr 27, 2026
7eccd54
test(training): add unit tests for rl launch script
WilliamBerryiii Apr 27, 2026
608a569
test(rl): add coverage for launch_rsl_rl module
WilliamBerryiii Apr 27, 2026
357e54c
test(rl): add coverage for launch module
WilliamBerryiii Apr 27, 2026
e6b4d90
test(extension): cover DatasetFormatHandler protocol method bodies
WilliamBerryiii Apr 27, 2026
2097ad7
test(rl): patch AzureConfigError in launch test for Windows compatibi…
WilliamBerryiii Apr 27, 2026
aca2bf6
test(training): add coverage for smoke_test_azure module
WilliamBerryiii Apr 27, 2026
ad61194
test(training): add coverage for rsl_rl train script
WilliamBerryiii Apr 28, 2026
8dabf89
chore(data-pipeline): bump requires-python to >=3.12
WilliamBerryiii Apr 28, 2026
6459edb
test(rl): cover parse_rsl_rl_cfg registry branch
WilliamBerryiii Apr 28, 2026
dbaf7e8
test(training): cover context.py storage, credential, and bootstrap b…
WilliamBerryiii Apr 28, 2026
c03afff
fix(evaluation): eliminate divide-by-zero RuntimeWarnings in SIL eval…
WilliamBerryiii Apr 28, 2026
c59ff72
test(training): add skrl_training coverage tests
WilliamBerryiii Apr 28, 2026
7a21494
ci(workflows): bump python/uv and gate dm-tools and training coverage…
WilliamBerryiii Apr 28, 2026
19a93a1
ci(workflows): bump python/uv and gate dm-tools and training coverage…
WilliamBerryiii Apr 28, 2026
432d01b
fix(data): repair dataviewer backend tests for missing azure SDK
WilliamBerryiii Apr 28, 2026
8564bc2
ci(scripts): enforce 80% coverage gate for dataviewer backend
WilliamBerryiii Apr 28, 2026
252daec
fix(fleet-inference): disable Hypothesis deadlines on matplotlib plot…
WilliamBerryiii Apr 28, 2026
db013ec
ci(workflows): enforce 80% coverage gate on data-pipeline pytests
WilliamBerryiii Apr 28, 2026
1493ee1
feat(inference): raise coverage to 99% and gate CI at 80%
WilliamBerryiii Apr 28, 2026
0e21ea5
chore(data-pipeline): add uv.lock for reproducible builds
WilliamBerryiii Apr 28, 2026
8ca1a01
Merge remote-tracking branch 'origin/main' into feat/441-dataviewer-b…
WilliamBerryiii Apr 29, 2026
e762662
style(tests): resolve ruff lint violations across changed test files
WilliamBerryiii Apr 29, 2026
e1babb4
chore(cspell): add testing and RL terms to technical dictionary
WilliamBerryiii Apr 29, 2026
9771eda
refactor(viewer): simplify ContentSettings assignment in labels router
WilliamBerryiii Apr 29, 2026
927a49c
refactor(viewer): simplify ContentSettings assignment in labels router
WilliamBerryiii Apr 29, 2026
37dadda
style(viewer): apply lint and formatting cleanup to backend tests
WilliamBerryiii Apr 29, 2026
2b19bf0
style(viewer): apply lint and formatting cleanup to backend tests
WilliamBerryiii Apr 29, 2026
03315e0
style(training): apply lint and formatting cleanup to training tests
WilliamBerryiii Apr 29, 2026
dd1844e
style(training): apply lint and formatting cleanup to training tests
WilliamBerryiii Apr 29, 2026
87f54ec
refactor(viewer): move hypothesis property tests to module level
WilliamBerryiii Apr 29, 2026
d00d348
♻️ refactor(viewer): move hypothesis property tests to module level
WilliamBerryiii Apr 29, 2026
e6a66ea
style(tests): resolve CodeQL static analysis findings
WilliamBerryiii Apr 29, 2026
20cfeb5
🎨 style(tests): resolve CodeQL static analysis findings
WilliamBerryiii Apr 29, 2026
6fbb16a
style(viewer-backend): apply ruff format to test_property_based.py
WilliamBerryiii Apr 29, 2026
f52f4b6
style(viewer-backend): apply ruff format to test_property_based.py
WilliamBerryiii Apr 29, 2026
5ede5f4
Merge remote-tracking branch 'origin/main' into feat/441-dataviewer-b…
WilliamBerryiii Apr 30, 2026
d51da4d
test(data): refactor async wrappers in viewer backend tests
WilliamBerryiii Apr 30, 2026
0d56ef6
test(training): remove duplicate test_rl_launch.py
WilliamBerryiii Apr 30, 2026
a21f945
test: justify hypothesis deadline overrides; raise dataviewer cov gat…
WilliamBerryiii Apr 30, 2026
62a026a
fix(data): repair pre-existing dataviewer backend handler tests
WilliamBerryiii Apr 30, 2026
b5521a7
chore: merge remote style commits into refactor branch
WilliamBerryiii Apr 30, 2026
b3e9f36
test(data): convert orchestrator tests to native async def pattern
WilliamBerryiii Apr 30, 2026
ee0bf61
fix(data): close unawaited _prefetch coroutine and apply ruff format
WilliamBerryiii May 1, 2026
8c7d4fb
Merge branch 'main' into feat/441-dataviewer-backend-coverage
WilliamBerryiii May 1, 2026
b8611c9
Merge branch 'main' into feat/441-dataviewer-backend-coverage
rezatnoMsirhC May 4, 2026
377ddf0
fix(pipeline): enable --cov-fail-under=80 in pyproject addopts
WilliamBerryiii May 5, 2026
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
17 changes: 17 additions & 0 deletions .cspell/general-technical.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2035,3 +2035,20 @@ vsmserver
envaccount
envcontainer
mycontainer
anoms
caplog
cfgs
ckpts
coro
dotdot
errstate
excinfo
fromlist
ftypmp
jpegbytes
matroska
myjob
reraises
topcam
notanum
fevil
2 changes: 1 addition & 1 deletion .github/workflows/dataviewer-backend-pytests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,7 +43,7 @@ jobs:
run: uv sync --extra dev --extra analysis --extra hdf5 --extra export --extra auth

- name: Run pytest with coverage
run: uv run pytest -v --cov=src --cov-report=xml:../../../logs/coverage-dataviewer.xml --cov-report=term-missing
run: uv run pytest -v --cov=src --cov-report=xml:../../../logs/coverage-dataviewer.xml --cov-report=term-missing --cov-fail-under=90

- name: Upload coverage.xml artifact
if: ${{ inputs.code-coverage && always() }}
Expand Down
11 changes: 11 additions & 0 deletions .github/workflows/main.yml
Original file line number Diff line number Diff line change
Expand Up @@ -157,6 +157,16 @@ jobs:
contents: read
id-token: write

# Evaluation domain pytest execution
evaluation-pytests:
name: Evaluation Pytest
uses: ./.github/workflows/evaluation-pytests.yml
with:
code-coverage: true
permissions:
contents: read
id-token: write

# Fuzz regression via deterministic corpus-based tests
fuzz-regression-tests:
name: Fuzz Regression Tests
Expand Down Expand Up @@ -268,6 +278,7 @@ jobs:
- pytest-inference
- dataviewer-frontend-tests
- dataviewer-backend-pytests
- evaluation-pytests
- python-lint
- terraform-lint
- terraform-validation
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pytest-data-pipeline.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
--cov=data-pipeline/capture
--cov-report=term-missing
--cov-report=xml:logs/coverage-data-pipeline.xml
--cov-fail-under=80

- name: Upload coverage.xml artifact
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pytest-dm-tools.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
--cov=data-management/tools
--cov-report=term-missing
--cov-report=xml:logs/coverage-dm-tools.xml
--cov-fail-under=80

- name: Upload coverage.xml artifact
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pytest-inference.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
--cov=fleet-deployment/inference
--cov-report=term-missing
--cov-report=xml:logs/coverage-inference.xml
--cov-fail-under=80

- name: Upload coverage.xml artifact
if: always()
Expand Down
1 change: 1 addition & 0 deletions .github/workflows/pytest-training.yml
Original file line number Diff line number Diff line change
Expand Up @@ -43,6 +43,7 @@ jobs:
--cov=training
--cov-report=term-missing
--cov-report=xml:logs/coverage-training.xml
--cov-fail-under=80

- name: Upload coverage.xml artifact
if: always()
Expand Down
9 changes: 9 additions & 0 deletions data-management/viewer/backend/pyproject.toml
Original file line number Diff line number Diff line change
Expand Up @@ -78,3 +78,12 @@ constraint-dependencies = ["pygments==2.20.0"]
[tool.pytest.ini_options]
asyncio_mode = "auto"
testpaths = ["tests"]

[tool.coverage.run]
source = ["src"]
branch = true
omit = ["src/**/conftest.py", "src/**/__init__.py"]

[tool.coverage.report]
show_missing = true
precision = 2
10 changes: 7 additions & 3 deletions data-management/viewer/backend/src/api/routers/labels.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,11 @@
if TYPE_CHECKING:
from ..storage.blob_dataset import BlobDatasetProvider

try:
from azure.storage.blob import ContentSettings
except ImportError:
ContentSettings = None

logger = logging.getLogger(__name__)

router = APIRouter()
Expand Down Expand Up @@ -142,16 +147,15 @@ async def load(self, dataset_id: str) -> DatasetLabelsFile:

async def save(self, dataset_id: str, labels_file: DatasetLabelsFile) -> None:
try:
from azure.storage.blob import ContentSettings

client = await self._provider._get_client()
container = client.get_container_client(self._provider.container_name)
blob_client = container.get_blob_client(self._blob_path(dataset_id))
content = json.dumps(labels_file.model_dump(), indent=2).encode("utf-8")
content_settings = ContentSettings(content_type="application/json") if ContentSettings is not None else None
await blob_client.upload_blob(
content,
overwrite=True,
content_settings=ContentSettings(content_type="application/json"),
content_settings=content_settings,
)
except Exception as e:
logger.error(
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -652,11 +652,13 @@ async def _prefetch() -> None:
# Clean up completed tasks
self._prefetch_tasks = {t for t in self._prefetch_tasks if not t.done()}

coro = _prefetch()
try:
task = asyncio.create_task(_prefetch())
task = asyncio.create_task(coro)
self._prefetch_tasks.add(task)
task.add_done_callback(self._prefetch_tasks.discard)
except RuntimeError as error:
coro.close()
logger.debug("Skipping episode prefetch for episode %d: %s", int(episode_idx), error)

def is_safe_video_path(self, video_path: str) -> bool:
Expand Down
13 changes: 11 additions & 2 deletions data-management/viewer/backend/src/api/storage/azure.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,17 @@

AZURE_AVAILABLE = True
except ImportError:
HttpResponseError = Exception
ResourceNotFoundError = Exception
# Distinct sentinel subclasses so `except` clauses don't accidentally
# match unrelated exceptions when the SDK isn't installed. Tests patch
# these module attributes to inject their own classes.
class _HttpResponseErrorStub(Exception):
"""Sentinel for HttpResponseError when azure SDK is unavailable."""

class _ResourceNotFoundErrorStub(Exception):
"""Sentinel for ResourceNotFoundError when azure SDK is unavailable."""

HttpResponseError = _HttpResponseErrorStub
ResourceNotFoundError = _ResourceNotFoundErrorStub
DefaultAzureCredential = None
ContentSettings = None
BlobServiceClient = None
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,58 @@
"""Tests for detection Pydantic models."""

from __future__ import annotations

import pytest
from pydantic import ValidationError

from src.api.models.detection import (
ClassSummary,
Detection,
DetectionRequest,
DetectionResult,
EpisodeDetectionSummary,
)


class TestDetectionRequest:
def test_defaults(self):
req = DetectionRequest()
assert req.frames is None
assert req.confidence == 0.25
assert req.model == "yolo11n"

def test_validate_frames_none_returns_none(self):
req = DetectionRequest(frames=None)
assert req.frames is None

def test_validate_frames_valid_list(self):
req = DetectionRequest(frames=[0, 1, 5, 10])
assert req.frames == [0, 1, 5, 10]

def test_validate_frames_negative_raises(self):
with pytest.raises(ValidationError, match="non-negative"):
DetectionRequest(frames=[0, -1, 2])

def test_confidence_out_of_range(self):
with pytest.raises(ValidationError):
DetectionRequest(confidence=1.5)


class TestDetectionModels:
def test_detection_instantiation(self):
det = Detection(class_id=0, class_name="person", confidence=0.9, bbox=(0.0, 0.0, 10.0, 20.0))
assert det.class_id == 0
assert det.bbox == (0.0, 0.0, 10.0, 20.0)

def test_detection_result_defaults(self):
result = DetectionResult(frame=3, processing_time_ms=12.5)
assert result.detections == []

def test_class_summary(self):
summary = ClassSummary(count=4, avg_confidence=0.75)
assert summary.count == 4

def test_episode_summary_defaults(self):
summary = EpisodeDetectionSummary(total_frames=10, processed_frames=5, total_detections=2)
assert summary.detections_by_frame == []
assert summary.class_summary == {}
Empty file.
Loading
Loading