Files
wehub-resource-sync 16031aae96
CPU tests Workflow / Testing (ubuntu-latest, 3.12) (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.13) (push) Failing after 0s
Mypy Type Check / Type Check (push) Failing after 0s
Docs/Test WorkFlow / Test docs build (push) Failing after 1s
PR Conflict Labeler / labeling (push) Failing after 1s
Dependency resolution / Resolve [tflite] extra — Python 3.12 (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.10) (push) Failing after 0s
Smoke Tests / try-all-models (ubuntu-latest, 3.13) (push) Failing after 1s
CPU tests Workflow / build-pkg (push) Failing after 1s
CPU tests Workflow / Testing (ubuntu-latest, 3.10) (push) Failing after 0s
CPU tests Workflow / Testing (ubuntu-latest, 3.11) (push) Failing after 0s
Smoke Tests / try-all-models (macos-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (macos-latest, 3.13) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.10) (push) Has been cancelled
Smoke Tests / try-all-models (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (macos-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.10) (push) Has been cancelled
CPU tests Workflow / Testing (windows-latest, 3.13) (push) Has been cancelled
CPU tests Workflow / testing-guardian (push) Has been cancelled
GPU tests Workflow / Testing (push) Has been cancelled
chore: import upstream snapshot with attribution
2026-07-13 12:26:24 +08:00

152 lines
5.4 KiB
Python

# ------------------------------------------------------------------------
# RF-DETR
# Copyright (c) 2025 Roboflow. All Rights Reserved.
# Licensed under the Apache License, Version 2.0 [see LICENSE for details]
# ------------------------------------------------------------------------
import shutil
from pathlib import Path
from typing import Any, Generator
import pytest
# NOTE: Model weights (rf-detr-*.pth) download to the CWD (typically tests/ when running pytest).
# This is a known limitation. Route: change pretrain_weights default to
# platformdirs.user_cache_dir("rfdetr") in a future PR.
from rfdetr.datasets.synthetic import DatasetSplitRatios, generate_coco_dataset
from rfdetr.utilities.reproducibility import seed_all
@pytest.fixture(scope="session", autouse=True)
def _prewarm_dinov2_cache() -> None:
"""Download DINOv2 backbone weights once per test session.
HuggingFace hub uses file-level locking internally, so concurrent xdist
workers block on each other rather than issuing duplicate network requests.
After the first worker finishes, all others read from the local disk cache.
Examples:
This fixture is autouse — no explicit reference needed in tests.
"""
import os
if os.environ.get("RFDETR_SKIP_DINOV2_PREWARM") == "1":
return
from huggingface_hub import snapshot_download
try:
snapshot_download(
"facebook/dinov2-with-registers-base",
ignore_patterns=["*.msgpack", "flax_model*", "tf_model*", "rust_model*"],
)
except Exception as exc:
pytest.skip(f"Skipping DINOv2 cache prewarm (snapshot_download failed): {exc}")
@pytest.fixture(autouse=True)
def reset_random_seeds() -> None:
"""Reset all RNG sources before every test for reproducibility."""
seed_all()
@pytest.fixture
def reset_build_namespace_warning_state() -> Generator[None, Any, None]:
"""Reset ``build_namespace`` deprecation call counters before each test.
``@deprecated(..., num_warns=1)`` emits only once per process by default. This fixture makes warning assertions
deterministic regardless of test order.
"""
from rfdetr._namespace import build_namespace
state = build_namespace._state
snapshot = (state.called, state.warned_calls, dict(state.warned_args))
state.called = 0
state.warned_calls = 0
state.warned_args = {}
try:
yield
finally:
state.called = snapshot[0]
state.warned_calls = snapshot[1]
state.warned_args = snapshot[2]
@pytest.fixture(scope="session")
def synthetic_shape_dataset_dir(tmp_path_factory: pytest.TempPathFactory) -> Generator[Path, Any, None]:
"""Build a synthetic COCO-style dataset on disk and clean it up after tests.
Args:
tmp_path_factory: Pytest factory for temporary directories.
Yields:
Path to the synthetic dataset directory.
"""
seed_all()
dataset_dir = tmp_path_factory.mktemp("synthetic_dataset")
generate_coco_dataset(
output_dir=str(dataset_dir),
num_images=100,
img_size=224,
class_mode="shape",
min_objects=3,
max_objects=7,
split_ratios=DatasetSplitRatios(train=0.8, val=0.2, test=0.0),
)
val_dir = dataset_dir / "val"
valid_dir = dataset_dir / "valid"
if val_dir.exists() and not valid_dir.exists():
val_dir.rename(valid_dir)
test_dir = dataset_dir / "test"
if not test_dir.exists():
test_dir.mkdir(parents=True, exist_ok=True)
(test_dir / "_annotations.coco.json").write_text((valid_dir / "_annotations.coco.json").read_text())
# Ensure test split has corresponding images referenced by the annotations
for item in valid_dir.iterdir():
if item.is_file() and item.name != "_annotations.coco.json":
shutil.copy2(item, test_dir / item.name)
yield dataset_dir
shutil.rmtree(dataset_dir)
@pytest.fixture(scope="session")
def synthetic_shape_segmentation_dataset_dir(
tmp_path_factory: pytest.TempPathFactory,
) -> Generator[Path, Any, None]:
"""Build a synthetic COCO-style dataset with polygon segmentation annotations.
Same layout as :func:`synthetic_shape_dataset_dir` but every annotation includes a ``segmentation`` polygon field so
the dataset can be used to train or evaluate segmentation models.
Args:
tmp_path_factory: Pytest factory for temporary directories.
Yields:
Path to the synthetic segmentation dataset directory.
"""
seed_all()
dataset_dir = tmp_path_factory.mktemp("synthetic_seg_dataset")
generate_coco_dataset(
output_dir=str(dataset_dir),
num_images=100,
img_size=224,
class_mode="shape",
min_objects=3,
max_objects=7,
split_ratios=DatasetSplitRatios(train=0.8, val=0.2, test=0.0),
with_segmentation=True,
)
val_dir = dataset_dir / "val"
valid_dir = dataset_dir / "valid"
if val_dir.exists() and not valid_dir.exists():
val_dir.rename(valid_dir)
test_dir = dataset_dir / "test"
if not test_dir.exists():
test_dir.mkdir(parents=True, exist_ok=True)
(test_dir / "_annotations.coco.json").write_text((valid_dir / "_annotations.coco.json").read_text())
for item in valid_dir.iterdir():
if item.is_file() and item.name != "_annotations.coco.json":
shutil.copy2(item, test_dir / item.name)
yield dataset_dir
shutil.rmtree(dataset_dir)