diff --git a/mmengine/utils/package_utils.py b/mmengine/utils/package_utils.py index 8abf4965..b224625f 100644 --- a/mmengine/utils/package_utils.py +++ b/mmengine/utils/package_utils.py @@ -24,7 +24,13 @@ def is_installed(package: str) -> bool: get_distribution(package) return True except pkg_resources.DistributionNotFound: - return importlib.util.find_spec(package) is not None + spec = importlib.util.find_spec(package) + if spec is None: + return False + elif spec.origin is not None: + return True + else: + return False def get_installed_path(package: str) -> str: @@ -54,20 +60,12 @@ def get_installed_path(package: str) -> str: if spec is not None: if spec.origin is not None: return osp.dirname(spec.origin) - # For namespace packages, the origin is None, and the first path - # in submodule_search_locations will be returned. - # namespace packages: https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ # noqa: E501 - elif spec.submodule_search_locations is not None: - locations = spec.submodule_search_locations - if isinstance(locations, list): - return locations[0] - else: - # `submodule_search_locations` is not subscriptable in - # python3.7. There for we use `_path` to get the first - # path. - return locations._path[0] # type: ignore else: - raise e + # `get_installed_path` cannot get the installed path of + # namespace packages + raise RuntimeError( + f'{package} is a namespace package, which is invalid ' + 'for `get_install_path`') else: raise e diff --git a/tests/test_utils/test_package_utils.py b/tests/test_utils/test_package_utils.py index c23d1c31..bed91b6c 100644 --- a/tests/test_utils/test_package_utils.py +++ b/tests/test_utils/test_package_utils.py @@ -1,7 +1,9 @@ # Copyright (c) OpenMMLab. All rights reserved. import os.path as osp import sys -from pathlib import Path + +import pkg_resources +import pytest from mmengine.utils import get_installed_path, is_installed @@ -10,32 +12,26 @@ def test_is_installed(): # TODO: Windows CI may failed in unknown reason. Skip check the value is_installed('mmengine') - # package set by PYTHONPATH - assert not is_installed('py_config') - sys.path.append(osp.abspath(osp.join(osp.dirname(__file__), '..'))) - assert is_installed('test_utils') + # If there is `__init__.py` in the directory which is added into + # `sys.path`, the directory will be recognized as a package. + PYTHONPATH = osp.abspath( + osp.join(osp.dirname(__file__), '..', '..', 'mmengine')) + sys.path.append(PYTHONPATH) + assert is_installed('optim') sys.path.pop() -def test_get_install_path(tmp_path: Path): +def test_get_install_path(): # TODO: Windows CI may failed in unknown reason. Skip check the value get_installed_path('mmengine') # get path for package "installed" by setting PYTHONPATH - PYTHONPATH = osp.abspath(osp.join( - osp.dirname(__file__), - '..', - )) + PYTHONPATH = osp.abspath(osp.join(osp.dirname(__file__), '..')) + PYTHONPATH = osp.abspath( + osp.join(osp.dirname(__file__), '..', '..', 'mmengine')) sys.path.append(PYTHONPATH) - res_path = get_installed_path('test_utils') - assert osp.join(PYTHONPATH, 'test_utils') == res_path + assert get_installed_path('optim') == osp.join(PYTHONPATH, 'optim') + sys.path.pop() - # return the first path for namespace package - # See more information about namespace package in: - # https://packaging.python.org/en/latest/guides/packaging-namespace-packages/ # noqa:E501 - (tmp_path / 'test_utils').mkdir() - sys.path.insert(-1, str(tmp_path)) - res_path = get_installed_path('test_utils') - assert osp.abspath(osp.join(tmp_path, 'test_utils')) == res_path - sys.path.pop() - sys.path.pop() + with pytest.raises(pkg_resources.DistributionNotFound): + get_installed_path('unknown')