From d154fee1b1cda3b1d7620dc3902eb535779fc6a6 Mon Sep 17 00:00:00 2001 From: alex Date: Thu, 2 Jul 2026 11:22:23 +0200 Subject: [PATCH] fix: LazyProvider no longer trigger eager module resolution --- tests/experimental/test_lazy_provider.py | 21 +++++++++++++++++++++ that_depends/experimental/providers.py | 5 ++++- 2 files changed, 25 insertions(+), 1 deletion(-) diff --git a/tests/experimental/test_lazy_provider.py b/tests/experimental/test_lazy_provider.py index 083f97f..8581929 100644 --- a/tests/experimental/test_lazy_provider.py +++ b/tests/experimental/test_lazy_provider.py @@ -1,5 +1,8 @@ +from unittest.mock import Mock + import pytest +from that_depends import providers from that_depends.experimental import LazyProvider @@ -28,3 +31,21 @@ def test_lazy_provider_incorrect_import_string() -> None: p = LazyProvider("some.random.path") with pytest.raises(ImportError): p.resolve_sync() + + +def test_lazy_provider_resolves_module_and_provider_strings() -> None: + p = LazyProvider(module_string="tests.experimental.test_container_2", provider_string="Container2.obj_2") + + assert p.resolve_sync() == 2 # noqa: PLR2004 + + +def test_collection_registration_does_not_resolve_lazy_provider(monkeypatch: pytest.MonkeyPatch) -> None: + import_module_mock = Mock() + monkeypatch.setattr("that_depends.experimental.providers.importlib.import_module", import_module_mock) + + lazy_provider = LazyProvider(module_string="some.module", provider_string="Container.provider") + + providers.Dict(dep=lazy_provider) + providers.List(lazy_provider) + + import_module_mock.assert_not_called() diff --git a/that_depends/experimental/providers.py b/that_depends/experimental/providers.py index 6a5b1ec..0a1f27d 100644 --- a/that_depends/experimental/providers.py +++ b/that_depends/experimental/providers.py @@ -16,7 +16,7 @@ _IMPORT_STRING_REGEX = re.compile(r"^[a-zA-Z_][a-zA-Z0-9_]*(\.[a-zA-Z_][a-zA-Z0-9_]*)*$") -class LazyProvider(SupportsTeardown, SupportsContext[Any], AbstractProvider[Any]): +class LazyProvider(AbstractProvider[Any], SupportsTeardown, SupportsContext[Any]): """Lazily imports and provides a provider from a module.""" @overload @@ -175,5 +175,8 @@ def reset_override_sync( @typing_extensions.override def __getattr__(self, attr_name: str) -> typing.Any: + if attr_name.startswith("_"): + msg = f"'{type(self)}' object has no attribute '{attr_name}'" + raise AttributeError(msg) provider = self._get_provider() return getattr(provider, attr_name)