diff --git a/src/linkml_reference_validator/plugins/__init__.py b/src/linkml_reference_validator/plugins/__init__.py index eef6d6c..6a7cb14 100644 --- a/src/linkml_reference_validator/plugins/__init__.py +++ b/src/linkml_reference_validator/plugins/__init__.py @@ -1,7 +1,14 @@ """LinkML validation plugins for reference validation.""" -from linkml_reference_validator.plugins.reference_validation_plugin import ( - ReferenceValidationPlugin, -) +from importlib.util import find_spec -__all__ = ["ReferenceValidationPlugin"] +# `linkml` is an optional dependency. Expose the LinkML plugin only when LinkML is available. +__all__: list[str] +if find_spec("linkml") is not None and find_spec("linkml.validator") is not None: + from linkml_reference_validator.plugins.reference_validation_plugin import ( # noqa: F401 + ReferenceValidationPlugin, + ) + + __all__ = ["ReferenceValidationPlugin"] +else: + __all__ = [] diff --git a/tests/test_optional_linkml_dependency.py b/tests/test_optional_linkml_dependency.py new file mode 100644 index 0000000..ca50d97 --- /dev/null +++ b/tests/test_optional_linkml_dependency.py @@ -0,0 +1,51 @@ +"""Tests for running without optional `linkml` dependency installed.""" + +import importlib +import sys +from importlib import util as importlib_util + + +def test_cli_imports_without_linkml(monkeypatch): + """Importing the CLI should not require `linkml` to be installed.""" + + real_find_spec = importlib_util.find_spec + + def fake_find_spec(name: str, *args, **kwargs): # type: ignore[no-untyped-def] + if name == "linkml" or name.startswith("linkml."): + return None + return real_find_spec(name, *args, **kwargs) + + monkeypatch.setattr(importlib_util, "find_spec", fake_find_spec) + + # Force a clean import of our package modules under the "no linkml" condition + for mod in list(sys.modules): + if mod.startswith("linkml_reference_validator"): + del sys.modules[mod] + + cli = importlib.import_module("linkml_reference_validator.cli") + assert getattr(cli, "app", None) is not None + + +def test_plugins_package_imports_without_linkml(monkeypatch): + """Importing `linkml_reference_validator.plugins` should not require `linkml`.""" + + real_find_spec = importlib_util.find_spec + + def fake_find_spec(name: str, *args, **kwargs): # type: ignore[no-untyped-def] + if name == "linkml" or name.startswith("linkml."): + return None + return real_find_spec(name, *args, **kwargs) + + monkeypatch.setattr(importlib_util, "find_spec", fake_find_spec) + + for mod in list(sys.modules): + if mod.startswith("linkml_reference_validator"): + del sys.modules[mod] + + plugins = importlib.import_module("linkml_reference_validator.plugins") + assert getattr(plugins, "__all__", None) == [] + + + + +