def test__load__with_already_loaded_files(self, patch_injection_container,
                                              patch_open):
        # given
        patch_injection_container(
            "get_caller_filepath",
            return_value=os.path.join("fake", "path", "file.py"),
        )
        mocked_file_1 = MagicMock(spec=os.DirEntry)
        mocked_file_1.path = os.path.join("fake", "path", "file_1.py")
        mocked_file_2 = MagicMock(spec=os.DirEntry)
        mocked_file_2.path = os.path.join("fake", "path", "file_2.py")
        file_collector = MagicMock()
        file_collector.collect.return_value = {mocked_file_1, mocked_file_2}
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(
            read_data=
            "from injectable import injectable\n@injectable\nclass A: ...")
        run_path = patch_injection_container("run_path")
        InjectionContainer.load()

        # when
        InjectionContainer.load()

        # then
        assert file_collector.collect.call_count == 2
        assert run_path.call_count == 2
        assert len(InjectionContainer.LOADED_FILEPATHS) == 2
    def test__load_dependencies_from__with_files_with_injectables(
            self, patch_injection_container, patch_open):
        # given
        root = "/" if os.name != "nt" else "C:\\"
        search_path = os.path.join(root, "fake", "path")
        namespace = DEFAULT_NAMESPACE
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(
            read_data=
            "from injectable import injectable\n@injectable\nclass A: ...")
        run_path = patch_injection_container("run_path")

        # when
        InjectionContainer.load_dependencies_from(search_path, namespace)

        # then
        assert file_collector.collect.called is True
        assert run_path.call_count == 2
    def test__load__when_runpy_run_module_fails_in_pytest_corner_case(
            self, patch_injection_container, patch_open):
        # given
        patch_injection_container(
            "get_caller_filepath",
            return_value=os.path.join("fake", "path", "file.py"),
        )
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(
            read_data=
            "from injectable import injectable\n@injectable\nclass A: ...")
        patch_injection_container("module_finder")
        run_module = patch_injection_container("run_module")

        def raise_attribute_error(*args, **kwargs):
            raise AttributeError()

        run_module.side_effect = raise_attribute_error
        run_path = patch_injection_container("run_path")

        # when
        InjectionContainer.load()

        # then
        assert file_collector.collect.called is True
        assert run_module.call_count == 2
        assert run_path.call_count == 2
    def test__load__with_files_without_injectables(self,
                                                   patch_injection_container,
                                                   patch_open):
        # given
        patch_injection_container(
            "get_caller_filepath",
            return_value=os.path.join("fake", "path", "file.py"),
        )
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(read_data='"""not injectable"""')
        run_path = patch_injection_container("run_path")

        # when
        InjectionContainer.load()

        # then
        assert file_collector.collect.called is True
        assert run_path.called is False
    def test__load__with_files_with_injectables(self,
                                                patch_injection_container,
                                                patch_open):
        # given
        patch_injection_container(
            "get_caller_filepath",
            return_value=os.path.join("fake", "path", "file.py"),
        )
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(
            read_data=
            "from injectable import injectable\n@injectable\nclass A: ...")
        patch_injection_container("module_finder")
        run_module = patch_injection_container("run_module")
        run_path = patch_injection_container("run_path")

        # when
        InjectionContainer.load()

        # then
        assert file_collector.collect.called is True
        assert run_module.call_count == 2
        assert run_path.call_count == 0
    def test__load_dependencies_from__with_files_without_injectables(
            self, patch_injection_container, patch_open):
        # given
        root = "/" if os.name != "nt" else "C:\\"
        search_path = os.path.join(root, "fake", "path")
        namespace = DEFAULT_NAMESPACE
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(read_data='"""not injectable"""')
        patch_injection_container("find_module_name")
        spec = MagicMock()
        patch_injection_container("spec_from_file_location", return_value=spec)
        patch_injection_container("module_from_spec")

        # when
        InjectionContainer.load_dependencies_from(search_path, namespace)

        # then
        assert file_collector.collect.called is True
        assert spec.loader.exec_module.called is False
    def test__load__with_files_without_injectables(self,
                                                   patch_injection_container,
                                                   patch_open):
        # given
        patch_injection_container(
            "get_caller_filepath",
            return_value=os.path.join("fake", "path", "file.py"),
        )
        file_collector = MagicMock()
        file_collector.collect.return_value = {
            MagicMock(spec=os.DirEntry),
            MagicMock(spec=os.DirEntry),
        }
        patch_injection_container(
            "PythonFileCollector",
            return_value=file_collector,
        )
        patch_open(read_data='"""not injectable"""')
        patch_injection_container("find_module_name")
        spec = MagicMock()
        patch_injection_container("spec_from_file_location", return_value=spec)
        patch_injection_container("module_from_spec")

        # when
        InjectionContainer.load()

        # then
        assert file_collector.collect.called is True
        assert spec.loader.exec_module.called is False
 def decorator(klass: T, direct_call: bool = False) -> T:
     steps_back = 3 if direct_call else 2
     caller_filepath = get_caller_filepath(steps_back)
     if caller_filepath == InjectionContainer.LOADING_FILEPATH:
         InjectionContainer._register_injectable(
             klass, caller_filepath, qualifier, primary, namespace, group, singleton
         )
     return klass
    def test__load_dependencies_from__leaves_loading_vars_clean(
            self, patch_injection_container):
        # given
        root = "/" if os.name != "nt" else "C:\\"
        search_path = os.path.join(root, "fake", "path")
        namespace = DEFAULT_NAMESPACE
        patch_injection_container("PythonFileCollector")

        # when
        InjectionContainer.load_dependencies_from(search_path, namespace)

        # then
        assert InjectionContainer.LOADING_FILEPATH is None
        assert InjectionContainer.LOADING_DEFAULT_NAMESPACE is None
 def decorator(fn: Callable[..., T]) -> Callable[..., T]:
     caller_filepath = get_caller_filepath()
     if caller_filepath == InjectionContainer.LOADING_FILEPATH:
         InjectionContainer._register_factory(
             fn,
             caller_filepath,
             dependency,
             qualifier,
             primary,
             namespace,
             group,
             singleton,
         )
     return fn
    def test__load_dependencies_from__regular_call(self,
                                                   patch_injection_container):
        # given
        root = "/" if os.name != "nt" else "C:\\"
        search_path = os.path.join(root, "fake", "path")
        namespace = DEFAULT_NAMESPACE
        file_collector = MagicMock()
        patch_injection_container("PythonFileCollector",
                                  return_value=file_collector)

        # when
        InjectionContainer.load_dependencies_from(search_path, namespace)

        # then
        assert file_collector.collect.called is True