| # SPDX-FileCopyrightText: Copyright (c) 2025 NVIDIA CORPORATION & AFFILIATES. All rights reserved. | |
| # SPDX-License-Identifier: Apache-2.0 | |
| # | |
| # Licensed under the Apache License, Version 2.0 (the "License"); | |
| # you may not use this file except in compliance with the License. | |
| # You may obtain a copy of the License at | |
| # | |
| # http://www.apache.org/licenses/LICENSE-2.0 | |
| # | |
| # Unless required by applicable law or agreed to in writing, software | |
| # distributed under the License is distributed on an "AS IS" BASIS, | |
| # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| # See the License for the specific language governing permissions and | |
| # limitations under the License. | |
| import pydoc | |
| from typing import Any | |
| """ | |
| `locate` provide ways to map a string (typically found | |
| in config files) to callable objects. | |
| """ | |
| __all__ = ["locate"] | |
| def _convert_target_to_string(t: Any) -> str: | |
| """ | |
| Inverse of ``locate()``. | |
| Args: | |
| t: any object with ``__module__`` and ``__qualname__`` | |
| """ | |
| module, qualname = t.__module__, t.__qualname__ | |
| # Compress the path to this object, e.g. ``module.submodule._impl.class`` | |
| # may become ``module.submodule.class``, if the later also resolves to the same | |
| # object. This simplifies the string, and also is less affected by moving the | |
| # class implementation. | |
| module_parts = module.split(".") | |
| for k in range(1, len(module_parts)): | |
| prefix = ".".join(module_parts[:k]) | |
| candidate = f"{prefix}.{qualname}" | |
| try: | |
| if locate(candidate) is t: | |
| return candidate | |
| except ImportError: | |
| pass | |
| return f"{module}.{qualname}" | |
| def locate(name: str) -> Any: | |
| """ | |
| Locate and return an object ``x`` using an input string ``{x.__module__}.{x.__qualname__}``, | |
| such as "module.submodule.class_name". | |
| Raise Exception if it cannot be found. | |
| """ | |
| obj = pydoc.locate(name) | |
| # Some cases (e.g. torch.optim.sgd.SGD) not handled correctly | |
| # by pydoc.locate. Try a private function from hydra. | |
| if obj is None: | |
| try: | |
| # from hydra.utils import get_method - will print many errors | |
| from hydra.utils import _locate | |
| except ImportError as e: | |
| raise ImportError(f"Cannot dynamically locate object {name}!") from e | |
| else: | |
| obj = _locate(name) # it raises if fails | |
| return obj | |