diff --git a/CHANGES.rst b/CHANGES.rst index c7e5889c..255bbd32 100644 --- a/CHANGES.rst +++ b/CHANGES.rst @@ -1,3 +1,10 @@ +v6.7.0 +====== + +* #453: When inferring top-level names that are importable for + distributions in ``package_distributions``, now symlinks to + other directories are honored. + v6.6.0 ====== diff --git a/importlib_metadata/__init__.py b/importlib_metadata/__init__.py index 68329964..8147d2f0 100644 --- a/importlib_metadata/__init__.py +++ b/importlib_metadata/__init__.py @@ -981,30 +981,34 @@ def _topmost(name: PackagePath) -> Optional[str]: return top if rest else None -def _get_toplevel_name(name: PackagePath) -> Optional[str]: +def _get_toplevel_name(name: PackagePath) -> str: """ Infer a possibly importable module name from a name presumed on sys.path. >>> _get_toplevel_name(PackagePath('foo.py')) 'foo' + >>> _get_toplevel_name(PackagePath('foo')) + 'foo' >>> _get_toplevel_name(PackagePath('foo.pyc')) 'foo' >>> _get_toplevel_name(PackagePath('foo/__init__.py')) 'foo' >>> _get_toplevel_name(PackagePath('foo.pth')) + 'foo.pth' >>> _get_toplevel_name(PackagePath('foo.dist-info')) + 'foo.dist-info' """ return _topmost(name) or ( # python/typeshed#10328 inspect.getmodulename(name) # type: ignore + or str(name) ) def _top_level_inferred(dist): opt_names = set(map(_get_toplevel_name, always_iterable(dist.files))) - @pass_none def importable_name(name): return '.' not in name diff --git a/tests/test_main.py b/tests/test_main.py index ad007595..79181bf4 100644 --- a/tests/test_main.py +++ b/tests/test_main.py @@ -9,6 +9,7 @@ from . import fixtures from ._context import suppress +from ._path import Symlink from importlib_metadata import ( Distribution, EntryPoint, @@ -399,6 +400,27 @@ def test_packages_distributions_all_module_types(self): assert not any(name.endswith('.dist-info') for name in distributions) + def test_packages_distributions_symlinked_top_level(self): + """ + Distribution is resolvable from a simple top-level symlink in RECORD. + See #452. + """ + + files: fixtures.FilesSpec = { + "symlinked_pkg-1.0.0.dist-info": { + "METADATA": """ + Name: symlinked-pkg + Version: 1.0.0 + """, + "RECORD": "symlinked,,\n", + }, + ".symlink.target": {}, + "symlinked": Symlink(".symlink.target"), + } + + fixtures.build_files(files, self.site_dir) + assert packages_distributions()['symlinked'] == ['symlinked-pkg'] + class PackagesDistributionsEggTest( fixtures.EggInfoPkg,