diff --git a/monai/engines/utils.py b/monai/engines/utils.py index 5c1d2f91b1..22a0e1de3d 100644 --- a/monai/engines/utils.py +++ b/monai/engines/utils.py @@ -22,7 +22,9 @@ if TYPE_CHECKING: from ignite.engine import EventEnum else: - EventEnum, _ = optional_import("ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "EventEnum") + EventEnum, _ = optional_import( + "ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "EventEnum", as_type="base" + ) __all__ = [ "IterationEvents", diff --git a/monai/engines/workflow.py b/monai/engines/workflow.py index 0886da6344..bf1d1ef1bf 100644 --- a/monai/engines/workflow.py +++ b/monai/engines/workflow.py @@ -24,7 +24,7 @@ from .utils import engine_apply_transform -IgniteEngine, _ = optional_import("ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Engine") +IgniteEngine, _ = optional_import("ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Engine", as_type="") State, _ = optional_import("ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "State") Events, _ = optional_import("ignite.engine", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Events") diff --git a/monai/handlers/ignite_metric.py b/monai/handlers/ignite_metric.py index f28923af68..d6f3f50144 100644 --- a/monai/handlers/ignite_metric.py +++ b/monai/handlers/ignite_metric.py @@ -19,9 +19,9 @@ from monai.utils import min_version, optional_import idist, _ = optional_import("ignite", IgniteInfo.OPT_IMPORT_VERSION, min_version, "distributed") -Metric, _ = optional_import("ignite.metrics", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Metric") +Metric, _ = optional_import("ignite.metrics", IgniteInfo.OPT_IMPORT_VERSION, min_version, "Metric", as_type="base") reinit__is_reduced, _ = optional_import( - "ignite.metrics.metric", IgniteInfo.OPT_IMPORT_VERSION, min_version, "reinit__is_reduced" + "ignite.metrics.metric", IgniteInfo.OPT_IMPORT_VERSION, min_version, "reinit__is_reduced", as_type="decorator" ) if TYPE_CHECKING: from ignite.engine import Engine diff --git a/monai/handlers/parameter_scheduler.py b/monai/handlers/parameter_scheduler.py index bf3d1cbe14..233abca2e0 100644 --- a/monai/handlers/parameter_scheduler.py +++ b/monai/handlers/parameter_scheduler.py @@ -45,10 +45,10 @@ def __init__( vc_kwargs: Dict, epoch_level: bool = False, name: Optional[str] = None, - event=Events.ITERATION_COMPLETED, + event=None, ): self.epoch_level = epoch_level - self.event = event + self.event = event if event is not None else Events.ITERATION_COMPLETED self._calculators = { "linear": self._linear, diff --git a/monai/utils/module.py b/monai/utils/module.py index 85c9bc3c73..06351ebe17 100644 --- a/monai/utils/module.py +++ b/monai/utils/module.py @@ -309,6 +309,7 @@ def optional_import( descriptor: str = OPTIONAL_IMPORT_MSG_FMT, version_args=None, allow_namespace_pkg: bool = False, + as_type: str = "default", ) -> Tuple[Any, bool]: """ Imports an optional module specified by `module` string. @@ -323,6 +324,10 @@ def optional_import( descriptor: a format string for the final error message when using a not imported module. version_args: additional parameters to the version checker. allow_namespace_pkg: whether importing a namespace package is allowed. Defaults to False. + as_type: there are cases where the optionally imported object is used as + a base class, or a decorator, the exceptions should raise accordingly. The current supported values + are "default" (call once to raise), "decorator" (call the constructor and the second call to raise), + and anything else will return a lazy class that can be used as a base class (call the constructor to raise). Returns: The imported module and a boolean flag indicating whether the import is successful. @@ -409,7 +414,22 @@ def __call__(self, *_args, **_kwargs): """ raise self._exception - return _LazyRaise(), False + def __getitem__(self, item): + raise self._exception + + def __iter__(self): + raise self._exception + + if as_type == "default": + return _LazyRaise(), False + + class _LazyCls(_LazyRaise): + def __init__(self, *_args, **kwargs): + super().__init__() + if not as_type.startswith("decorator"): + raise self._exception + + return _LazyCls, False def require_pkg( diff --git a/tests/min_tests.py b/tests/min_tests.py index 542e51b09d..bb43c5221f 100644 --- a/tests/min_tests.py +++ b/tests/min_tests.py @@ -207,10 +207,7 @@ def run_testsuit(): from monai.utils.module import load_submodules _, err_mod = load_submodules(sys.modules["monai"], True) - if err_mod: - print(err_mod) - # expecting that only engines and handlers are not imported - assert sorted(err_mod) == ["monai.engines", "monai.handlers"] + assert not err_mod # testing all modules test_runner = unittest.TextTestRunner(stream=sys.stdout, verbosity=2)