def _locate()

in hydra/_internal/utils.py [0:0]


def _locate(path: str) -> Union[type, Callable[..., Any]]:
    """
    Locate an object by name or dotted path, importing as necessary.
    This is similar to the pydoc function `locate`, except that it checks for
    the module from the given path from back to front.
    """
    if path == "":
        raise ImportError("Empty path")
    from importlib import import_module
    from types import ModuleType

    parts = [part for part in path.split(".") if part]
    for n in reversed(range(1, len(parts) + 1)):
        mod = ".".join(parts[:n])
        try:
            obj = import_module(mod)
        except Exception as exc_import:
            if n == 1:
                raise ImportError(f"Error loading module '{path}'") from exc_import
            continue
        break
    for m in range(n, len(parts)):
        part = parts[m]
        try:
            obj = getattr(obj, part)
        except AttributeError as exc_attr:
            if isinstance(obj, ModuleType):
                mod = ".".join(parts[: m + 1])
                try:
                    import_module(mod)
                except ModuleNotFoundError:
                    pass
                except Exception as exc_import:
                    raise ImportError(
                        f"Error loading '{path}': '{repr(exc_import)}'"
                    ) from exc_import
            raise ImportError(
                f"Encountered AttributeError while loading '{path}': {exc_attr}"
            ) from exc_attr
    if isinstance(obj, type):
        obj_type: type = obj
        return obj_type
    elif callable(obj):
        obj_callable: Callable[..., Any] = obj
        return obj_callable
    else:
        # reject if not callable & not a type
        raise ValueError(f"Invalid type ({type(obj)}) found for {path}")