fix leaking imports in minimal testing

This commit is contained in:
Steven Palma
2026-04-12 13:52:45 +02:00
parent 27292a3432
commit 2bf33ccb98
46 changed files with 256 additions and 121 deletions
+3 -1
View File
@@ -35,8 +35,10 @@ from concurrent import futures
import pytest
import torch
# Skip entire module if grpc is not available
# Skip entire module if required deps are not available
pytest.importorskip("grpc")
pytest.importorskip("serial", reason="pyserial is required (install lerobot[hardware])")
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
# -----------------------------------------------------------------------------
# End-to-end test
+3 -1
View File
@@ -25,8 +25,10 @@ from queue import Queue
import pytest
import torch
# Skip entire module if grpc is not available
# Skip entire module if required deps are not available
pytest.importorskip("grpc")
pytest.importorskip("serial", reason="pyserial is required (install lerobot[hardware])")
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
# -----------------------------------------------------------------------------
# Test fixtures
+21 -6
View File
@@ -17,24 +17,39 @@
import traceback
import pytest
from serial import SerialException
from lerobot.configs.types import FeatureType, PipelineFeatureType, PolicyFeature
from lerobot.utils.import_utils import is_package_available
from tests.utils import DEVICE
# Import fixture modules as plugins
# Import fixture modules as plugins.
# Fixtures that depend on optional packages are only registered when those packages are available,
# so that tests can be collected and run even with a minimal install.
pytest_plugins = [
"tests.fixtures.dataset_factories",
"tests.fixtures.files",
"tests.fixtures.hub",
"tests.fixtures.optimizers",
]
if is_package_available("datasets"):
pytest_plugins += [
"tests.fixtures.dataset_factories",
"tests.fixtures.files",
"tests.fixtures.hub",
]
def pytest_collection_finish():
print(f"\nTesting with {DEVICE=}")
def _is_serial_exception(exc: Exception) -> bool:
"""Check if an exception is a SerialException without requiring pyserial."""
if not is_package_available("pyserial", import_name="serial"):
return False
from serial import SerialException
return isinstance(exc, SerialException)
def _check_component_availability(component_type, available_components, make_component):
"""Generic helper to check if a hardware component is available"""
if component_type not in available_components:
@@ -53,7 +68,7 @@ def _check_component_availability(component_type, available_components, make_com
if isinstance(e, ModuleNotFoundError):
print(f"\nInstall module '{e.name}'")
elif isinstance(e, SerialException):
elif _is_serial_exception(e):
print("\nNo physical device detected.")
elif isinstance(e, ValueError) and "camera_index" in str(e):
print("\nNo physical camera detected.")
+5 -1
View File
@@ -16,7 +16,11 @@
from unittest.mock import patch
import datasets
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
import datasets # noqa: E402
import torch
from lerobot.datasets.aggregate import aggregate_datasets
+2
View File
@@ -18,6 +18,8 @@ from unittest.mock import patch
import numpy as np
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.compute_stats import (
RunningQuantileStats,
_assert_type_and_shape,
+2
View File
@@ -20,6 +20,8 @@ import json
import numpy as np
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.dataset_metadata import LeRobotDatasetMetadata
from lerobot.datasets.utils import INFO_PATH
from tests.fixtures.constants import DEFAULT_FPS, DUMMY_ROBOT_TYPE
+4
View File
@@ -15,6 +15,10 @@
# limitations under the License.
"""Contract tests for DatasetReader."""
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.dataset_reader import DatasetReader
from lerobot.utils.import_utils import get_safe_default_codec
+2
View File
@@ -21,6 +21,8 @@ import numpy as np
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.dataset_tools import (
add_features,
delete_episodes,
+4 -1
View File
@@ -16,7 +16,10 @@
import pytest
import torch
from datasets import Dataset
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from datasets import Dataset # noqa: E402
from huggingface_hub import DatasetCard
from lerobot.datasets.io_utils import hf_transform_to_torch
+2
View File
@@ -23,6 +23,8 @@ import pytest
import torch
from PIL import Image
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.dataset_writer import _encode_video_worker
from lerobot.datasets.lerobot_dataset import LeRobotDataset
from lerobot.datasets.utils import DEFAULT_IMAGE_PATH
+3
View File
@@ -21,6 +21,9 @@ from pathlib import Path
import numpy as np
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from huggingface_hub import HfApi
from PIL import Image
from safetensors.torch import load_file
+2
View File
@@ -13,6 +13,8 @@
# limitations under the License.
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.feature_utils import (
check_delta_timestamps,
get_delta_indices,
+2
View File
@@ -21,6 +21,8 @@ from safetensors.torch import load_file
from torchvision.transforms import v2
from torchvision.transforms.v2 import functional as F # noqa: N812
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.scripts.lerobot_imgtransform_viz import (
save_all_transforms,
save_each_transform,
+2
View File
@@ -20,6 +20,8 @@ import numpy as np
import pytest
from PIL import Image
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.image_writer import (
AsyncImageWriter,
image_array_to_pil_image,
+2
View File
@@ -25,6 +25,8 @@ from unittest.mock import Mock
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
import lerobot.datasets.dataset_metadata as dataset_metadata_module
import lerobot.datasets.lerobot_dataset as lerobot_dataset_module
from lerobot.datasets.dataset_metadata import LeRobotDatasetMetadata
@@ -19,6 +19,8 @@
import numpy as np
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.lerobot_dataset import LeRobotDataset
+4 -1
View File
@@ -17,7 +17,10 @@ import logging
import pytest
import torch
from datasets import Dataset
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from datasets import Dataset # noqa: E402
from lerobot.datasets.io_utils import (
hf_transform_to_torch,
+2
View File
@@ -17,6 +17,8 @@ import numpy as np
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.streaming_dataset import StreamingLeRobotDataset
from lerobot.datasets.utils import safe_shard
from lerobot.utils.constants import ACTION
@@ -20,10 +20,13 @@ import queue
import threading
from unittest.mock import patch
import av
import numpy as np
import pytest
pytest.importorskip("av", reason="av is required (install lerobot[dataset])")
import av # noqa: E402
from lerobot.datasets.video_utils import (
VALID_VIDEO_CODECS,
StreamingVideoEncoder,
+4 -1
View File
@@ -23,8 +23,11 @@ These tests verify that:
- Subtask handling gracefully handles missing data
"""
import pandas as pd
import pytest
pytest.importorskip("pandas", reason="pandas is required (install lerobot[dataset])")
import pandas as pd # noqa: E402
import torch
from lerobot.datasets.lerobot_dataset import LeRobotDataset
+2
View File
@@ -15,6 +15,8 @@
# limitations under the License.
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.scripts.lerobot_dataset_viz import visualize_dataset
+2
View File
@@ -19,6 +19,8 @@ from unittest.mock import patch
import pytest
pytest.importorskip("serial", reason="pyserial is required (install lerobot[hardware])")
from lerobot.motors.motors_bus import (
Motor,
MotorNormMode,
+1 -1
View File
@@ -31,7 +31,7 @@ from lerobot.policies.groot.processor_groot import make_groot_pre_post_processor
from lerobot.processor import PolicyProcessorPipeline
from lerobot.types import PolicyAction
from lerobot.utils.device_utils import auto_select_torch_device
from tests.utils import require_cuda # noqa: E402
from tests.utils import require_cuda
pytest.importorskip("transformers")
+5 -5
View File
@@ -19,12 +19,12 @@
import pytest
import torch
from lerobot.configs.types import FeatureType, PolicyFeature, RTCAttentionSchedule # noqa: E402
from lerobot.policies.factory import make_pre_post_processors # noqa: E402
from lerobot.policies.rtc.configuration_rtc import RTCConfig # noqa: E402
from lerobot.configs.types import FeatureType, PolicyFeature, RTCAttentionSchedule
from lerobot.policies.factory import make_pre_post_processors
from lerobot.policies.rtc.configuration_rtc import RTCConfig
from lerobot.policies.smolvla.configuration_smolvla import SmolVLAConfig # noqa: F401
from lerobot.utils.random_utils import set_seed # noqa: E402
from tests.utils import require_cuda, skip_if_package_missing # noqa: E402
from lerobot.utils.random_utils import set_seed
from tests.utils import require_cuda, skip_if_package_missing
@skip_if_package_missing("transformers")
+3
View File
@@ -20,6 +20,9 @@ from pathlib import Path
import einops
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from packaging import version
from safetensors.torch import load_file
+2
View File
@@ -10,6 +10,8 @@ import numpy as np
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.configs.types import FeatureType, NormalizationMode, PolicyFeature
from lerobot.datasets.compute_stats import get_feature_stats
from lerobot.datasets.lerobot_dataset import LeRobotDataset
+2
View File
@@ -25,6 +25,8 @@ import pytest
import torch
import torch.nn as nn
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.configs.types import FeatureType, PipelineFeatureType, PolicyFeature
from lerobot.datasets.pipeline_features import aggregate_pipeline_dataset_features
from lerobot.processor import (
+3
View File
@@ -19,6 +19,9 @@ from unittest.mock import patch
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from torch.multiprocessing import Event, Queue
from lerobot.utils.constants import OBS_STR
+3
View File
@@ -20,6 +20,9 @@ import time
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from torch.multiprocessing import Event, Queue
from lerobot.configs.train import TrainRLServerPipelineConfig
@@ -17,6 +17,8 @@
import draccus
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.scripts.lerobot_edit_dataset import (
ConvertImageToVideoConfig,
DeleteEpisodesConfig,
+4
View File
@@ -16,6 +16,10 @@
from unittest.mock import patch
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.scripts.lerobot_calibrate import CalibrateConfig, calibrate
from lerobot.scripts.lerobot_record import DatasetRecordConfig, RecordConfig, record
from lerobot.scripts.lerobot_replay import DatasetReplayConfig, ReplayConfig, replay
+2
View File
@@ -33,6 +33,8 @@ from pathlib import Path
import pytest
import torch
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.datasets.lerobot_dataset import LeRobotDataset
+2
View File
@@ -31,6 +31,8 @@ from pathlib import Path
import numpy as np
import pytest
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
from lerobot.configs.default import DatasetConfig
from lerobot.configs.policies import PreTrainedConfig
from lerobot.configs.train import TrainPipelineConfig
+1
View File
@@ -20,6 +20,7 @@ from collections.abc import Callable
import pytest
pytest.importorskip("grpc")
pytest.importorskip("datasets", reason="datasets is required (install lerobot[dataset])")
import torch # noqa: E402
+2
View File
@@ -21,6 +21,8 @@ from types import SimpleNamespace
import numpy as np
import pytest
pytest.importorskip("rerun", reason="rerun-sdk is required (install lerobot[viz])")
from lerobot.types import TransitionKey
from lerobot.utils.constants import OBS_STATE