diff --git a/.github/workflows/pr_dependency_test.yml b/.github/workflows/pr_dependency_test.yml index ba5cd1c76cbc..e89e71de6d75 100644 --- a/.github/workflows/pr_dependency_test.yml +++ b/.github/workflows/pr_dependency_test.yml @@ -6,6 +6,7 @@ on: - main paths: - "src/diffusers/**.py" + - "tests/**.py" push: branches: - main diff --git a/.github/workflows/pr_torch_dependency_test.yml b/.github/workflows/pr_torch_dependency_test.yml index 79569488ae21..27b4483ac5dd 100644 --- a/.github/workflows/pr_torch_dependency_test.yml +++ b/.github/workflows/pr_torch_dependency_test.yml @@ -6,6 +6,7 @@ on: - main paths: - "src/diffusers/**.py" + - "tests/**.py" push: branches: - main @@ -26,7 +27,7 @@ jobs: - name: Install dependencies run: | pip install -e . - pip install torch torchvision torchaudio pytest + pip install torch pytest - name: Check for soft dependencies run: | pytest tests/others/test_dependencies.py diff --git a/src/diffusers/pipelines/consisid/consisid_utils.py b/src/diffusers/pipelines/consisid/consisid_utils.py index c1646e15efbc..07bba890c383 100644 --- a/src/diffusers/pipelines/consisid/consisid_utils.py +++ b/src/diffusers/pipelines/consisid/consisid_utils.py @@ -5,10 +5,13 @@ import numpy as np import torch from PIL import Image, ImageOps -from torchvision.transforms import InterpolationMode -from torchvision.transforms.functional import normalize, resize -from ...utils import get_logger, load_image +from ...utils import get_logger, is_torchvision_available, load_image + + +if is_torchvision_available(): + from torchvision.transforms import InterpolationMode + from torchvision.transforms.functional import normalize, resize logger = get_logger(__name__) diff --git a/tests/others/test_dependencies.py b/tests/others/test_dependencies.py index db22f10c4b3c..b2e28077b131 100644 --- a/tests/others/test_dependencies.py +++ b/tests/others/test_dependencies.py @@ -13,16 +13,14 @@ # limitations under the License. import inspect -import unittest from importlib import import_module +import pytest -class DependencyTester(unittest.TestCase): + +class TestDependencies: def test_diffusers_import(self): - try: - import diffusers # noqa: F401 - except ImportError: - assert False + import diffusers # noqa: F401 def test_backend_registration(self): import diffusers @@ -52,3 +50,36 @@ def test_pipeline_imports(self): if hasattr(diffusers.pipelines, cls_name): pipeline_folder_module = ".".join(str(cls_module.__module__).split(".")[:3]) _ = import_module(pipeline_folder_module, str(cls_name)) + + def test_pipeline_module_imports(self): + """Import every pipeline submodule whose dependencies are satisfied, + to catch unguarded optional-dep imports (e.g., torchvision). + + Uses inspect.getmembers to discover classes that the lazy loader can + actually resolve (same self-filtering as test_pipeline_imports), then + imports the full module path instead of truncating to the folder level. + """ + import diffusers + import diffusers.pipelines + + failures = [] + all_classes = inspect.getmembers(diffusers, inspect.isclass) + + for cls_name, cls_module in all_classes: + if not hasattr(diffusers.pipelines, cls_name): + continue + if "dummy_" in cls_module.__module__: + continue + + full_module_path = cls_module.__module__ + try: + import_module(full_module_path) + except ImportError as e: + failures.append(f"{full_module_path}: {e}") + except Exception: + # Non-import errors (e.g., missing config) are fine; we only + # care about unguarded import statements. + pass + + if failures: + pytest.fail("Unguarded optional-dependency imports found:\n" + "\n".join(failures))