Script 'mail_helper' called by obssrc
Hello community,
here is the log from the commit of package python-importlib-metadata for
openSUSE:Factory checked in at 2023-04-16 16:06:41
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Comparing /work/SRC/openSUSE:Factory/python-importlib-metadata (Old)
and /work/SRC/openSUSE:Factory/.python-importlib-metadata.new.19717 (New)
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Package is "python-importlib-metadata"
Sun Apr 16 16:06:41 2023 rev:18 rq:1079571 version:6.3.0
Changes:
--------
---
/work/SRC/openSUSE:Factory/python-importlib-metadata/python-importlib-metadata.changes
2023-04-04 21:16:58.847874613 +0200
+++
/work/SRC/openSUSE:Factory/.python-importlib-metadata.new.19717/python-importlib-metadata.changes
2023-04-16 16:06:45.844709325 +0200
@@ -1,0 +2,12 @@
+Sat Apr 15 10:16:48 UTC 2023 - Dirk Müller <[email protected]>
+
+- update to 6.3.0:
+ * #115: Support ``installed-files.txt`` for
+ ``Distribution.files`` when present.
+ * #442: Fixed issue introduced in v6.1.0 where non-importable
+ * names (metadata dirs) began appearing in ``packages_distributions``.
+ * #384: ``PackageMetadata`` now stipulates an additional
+ ``get`` method allowing for easy querying of metadata keys that may
+ not be present
+
+-------------------------------------------------------------------
Old:
----
importlib_metadata-6.1.0.tar.gz
New:
----
importlib_metadata-6.3.0.tar.gz
++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
Other differences:
------------------
++++++ python-importlib-metadata.spec ++++++
--- /var/tmp/diff_new_pack.dcZrDv/_old 2023-04-16 16:06:46.352712253 +0200
+++ /var/tmp/diff_new_pack.dcZrDv/_new 2023-04-16 16:06:46.356712276 +0200
@@ -27,7 +27,7 @@
%{?!python_module:%define python_module() python3-%{**}}
%define skip_python2 1
Name: python-importlib-metadata%{psuffix}
-Version: 6.1.0
+Version: 6.3.0
Release: 0
Summary: Read metadata from Python packages
License: Apache-2.0
++++++ importlib_metadata-6.1.0.tar.gz -> importlib_metadata-6.3.0.tar.gz ++++++
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/.github/workflows/main.yml
new/importlib_metadata-6.3.0/.github/workflows/main.yml
--- old/importlib_metadata-6.1.0/.github/workflows/main.yml 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/.github/workflows/main.yml 2023-04-10
04:27:13.000000000 +0200
@@ -2,6 +2,9 @@
on: [push, pull_request]
+permissions:
+ contents: read
+
env:
# Environment variables to support color support (jaraco/skeleton#66):
# Request colored output from CLI tools supporting it. Different tools
@@ -130,6 +133,8 @@
TOXENV: diffcov
release:
+ permissions:
+ contents: write
needs:
- check
if: github.event_name == 'push' && contains(github.ref, 'refs/tags/')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/CHANGES.rst
new/importlib_metadata-6.3.0/CHANGES.rst
--- old/importlib_metadata-6.1.0/CHANGES.rst 2023-03-18 18:10:20.000000000
+0100
+++ new/importlib_metadata-6.3.0/CHANGES.rst 2023-04-10 04:27:13.000000000
+0200
@@ -1,3 +1,23 @@
+v6.3.0
+======
+
+* #115: Support ``installed-files.txt`` for ``Distribution.files``
+ when present.
+
+v6.2.1
+======
+
+* #442: Fixed issue introduced in v6.1.0 where non-importable
+ names (metadata dirs) began appearing in
+ ``packages_distributions``.
+
+v6.2.0
+======
+
+* #384: ``PackageMetadata`` now stipulates an additional ``get``
+ method allowing for easy querying of metadata keys that may not
+ be present.
+
v6.1.0
======
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/PKG-INFO
new/importlib_metadata-6.3.0/PKG-INFO
--- old/importlib_metadata-6.1.0/PKG-INFO 2023-03-18 18:10:38.770994400
+0100
+++ new/importlib_metadata-6.3.0/PKG-INFO 2023-04-10 04:27:32.096812500
+0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: importlib_metadata
-Version: 6.1.0
+Version: 6.3.0
Summary: Read metadata from Python packages
Home-page: https://github.com/python/importlib_metadata
Author: Jason R. Coombs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-6.1.0/importlib_metadata/__init__.py
new/importlib_metadata-6.3.0/importlib_metadata/__init__.py
--- old/importlib_metadata-6.1.0/importlib_metadata/__init__.py 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/importlib_metadata/__init__.py 2023-04-10
04:27:13.000000000 +0200
@@ -12,6 +12,7 @@
import functools
import itertools
import posixpath
+import contextlib
import collections
import inspect
@@ -461,8 +462,8 @@
:return: List of PackagePath for this distribution or None
Result is `None` if the metadata file that enumerates files
- (i.e. RECORD for dist-info or SOURCES.txt for egg-info) is
- missing.
+ (i.e. RECORD for dist-info, or installed-files.txt or
+ SOURCES.txt for egg-info) is missing.
Result may be empty if the metadata exists but is empty.
"""
@@ -475,9 +476,19 @@
@pass_none
def make_files(lines):
- return list(starmap(make_file, csv.reader(lines)))
+ return starmap(make_file, csv.reader(lines))
- return make_files(self._read_files_distinfo() or
self._read_files_egginfo())
+ @pass_none
+ def skip_missing_files(package_paths):
+ return list(filter(lambda path: path.locate().exists(),
package_paths))
+
+ return skip_missing_files(
+ make_files(
+ self._read_files_distinfo()
+ or self._read_files_egginfo_installed()
+ or self._read_files_egginfo_sources()
+ )
+ )
def _read_files_distinfo(self):
"""
@@ -486,10 +497,43 @@
text = self.read_text('RECORD')
return text and text.splitlines()
- def _read_files_egginfo(self):
+ def _read_files_egginfo_installed(self):
"""
- SOURCES.txt might contain literal commas, so wrap each line
- in quotes.
+ Read installed-files.txt and return lines in a similar
+ CSV-parsable format as RECORD: each file must be placed
+ relative to the site-packages directory, and must also be
+ quoted (since file names can contain literal commas).
+
+ This file is written when the package is installed by pip,
+ but it might not be written for other installation methods.
+ Hence, even if we can assume that this file is accurate
+ when it exists, we cannot assume that it always exists.
+ """
+ text = self.read_text('installed-files.txt')
+ # We need to prepend the .egg-info/ subdir to the lines in this file.
+ # But this subdir is only available in the PathDistribution's
self._path
+ # which is not easily accessible from this base class...
+ subdir = getattr(self, '_path', None)
+ if not text or not subdir:
+ return
+ with contextlib.suppress(Exception):
+ ret = [
+ str((subdir /
line).resolve().relative_to(self.locate_file('')))
+ for line in text.splitlines()
+ ]
+ return map('"{}"'.format, ret)
+
+ def _read_files_egginfo_sources(self):
+ """
+ Read SOURCES.txt and return lines in a similar CSV-parsable
+ format as RECORD: each file name must be quoted (since it
+ might contain literal commas).
+
+ Note that SOURCES.txt is not a reliable source for what
+ files are installed by a package. This file is generated
+ for a source archive, and the files that are present
+ there (e.g. setup.py) may not correctly reflect the files
+ that are present after the package has been installed.
"""
text = self.read_text('SOURCES.txt')
return text and map('"{}"'.format, text.splitlines())
@@ -902,4 +946,9 @@
f.parts[0] if len(f.parts) > 1 else inspect.getmodulename(f)
for f in always_iterable(dist.files)
}
- return filter(None, opt_names)
+
+ @pass_none
+ def importable_name(name):
+ return '.' not in name
+
+ return filter(importable_name, opt_names)
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/importlib_metadata/_meta.py
new/importlib_metadata-6.3.0/importlib_metadata/_meta.py
--- old/importlib_metadata-6.1.0/importlib_metadata/_meta.py 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/importlib_metadata/_meta.py 2023-04-10
04:27:13.000000000 +0200
@@ -18,6 +18,14 @@
def __iter__(self) -> Iterator[str]:
... # pragma: no cover
+ @overload
+ def get(self, name: str, failobj: None = None) -> Optional[str]:
+ ... # pragma: no cover
+
+ @overload
+ def get(self, name: str, failobj: _T) -> Union[str, _T]:
+ ... # pragma: no cover
+
# overload per python/importlib_metadata#435
@overload
def get_all(self, name: str, failobj: None = None) -> Optional[List[Any]]:
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-6.1.0/importlib_metadata.egg-info/PKG-INFO
new/importlib_metadata-6.3.0/importlib_metadata.egg-info/PKG-INFO
--- old/importlib_metadata-6.1.0/importlib_metadata.egg-info/PKG-INFO
2023-03-18 18:10:38.000000000 +0100
+++ new/importlib_metadata-6.3.0/importlib_metadata.egg-info/PKG-INFO
2023-04-10 04:27:32.000000000 +0200
@@ -1,6 +1,6 @@
Metadata-Version: 2.1
Name: importlib-metadata
-Version: 6.1.0
+Version: 6.3.0
Summary: Read metadata from Python packages
Home-page: https://github.com/python/importlib_metadata
Author: Jason R. Coombs
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore'
old/importlib_metadata-6.1.0/importlib_metadata.egg-info/SOURCES.txt
new/importlib_metadata-6.3.0/importlib_metadata.egg-info/SOURCES.txt
--- old/importlib_metadata-6.1.0/importlib_metadata.egg-info/SOURCES.txt
2023-03-18 18:10:38.000000000 +0100
+++ new/importlib_metadata-6.3.0/importlib_metadata.egg-info/SOURCES.txt
2023-04-10 04:27:32.000000000 +0200
@@ -44,6 +44,7 @@
prepare/example2/pyproject.toml
prepare/example2/example2/__init__.py
tests/__init__.py
+tests/_path.py
tests/fixtures.py
tests/py39compat.py
tests/test_api.py
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/tests/_path.py
new/importlib_metadata-6.3.0/tests/_path.py
--- old/importlib_metadata-6.1.0/tests/_path.py 1970-01-01 01:00:00.000000000
+0100
+++ new/importlib_metadata-6.3.0/tests/_path.py 2023-04-10 04:27:13.000000000
+0200
@@ -0,0 +1,104 @@
+# from jaraco.path 3.5
+
+import functools
+import pathlib
+from typing import Dict, Union
+
+try:
+ from typing import Protocol, runtime_checkable
+except ImportError: # pragma: no cover
+ # Python 3.7
+ from typing_extensions import Protocol, runtime_checkable # type: ignore
+
+
+FilesSpec = Dict[str, Union[str, bytes, 'FilesSpec']] # type: ignore
+
+
+@runtime_checkable
+class TreeMaker(Protocol):
+ def __truediv__(self, *args, **kwargs):
+ ... # pragma: no cover
+
+ def mkdir(self, **kwargs):
+ ... # pragma: no cover
+
+ def write_text(self, content, **kwargs):
+ ... # pragma: no cover
+
+ def write_bytes(self, content):
+ ... # pragma: no cover
+
+
+def _ensure_tree_maker(obj: Union[str, TreeMaker]) -> TreeMaker:
+ return obj if isinstance(obj, TreeMaker) else pathlib.Path(obj) # type:
ignore
+
+
+def build(
+ spec: FilesSpec,
+ prefix: Union[str, TreeMaker] = pathlib.Path(), # type: ignore
+):
+ """
+ Build a set of files/directories, as described by the spec.
+
+ Each key represents a pathname, and the value represents
+ the content. Content may be a nested directory.
+
+ >>> spec = {
+ ... 'README.txt': "A README file",
+ ... "foo": {
+ ... "__init__.py": "",
+ ... "bar": {
+ ... "__init__.py": "",
+ ... },
+ ... "baz.py": "# Some code",
+ ... }
+ ... }
+ >>> target = getfixture('tmp_path')
+ >>> build(spec, target)
+ >>> target.joinpath('foo/baz.py').read_text(encoding='utf-8')
+ '# Some code'
+ """
+ for name, contents in spec.items():
+ create(contents, _ensure_tree_maker(prefix) / name)
+
+
[email protected]
+def create(content: Union[str, bytes, FilesSpec], path):
+ path.mkdir(exist_ok=True)
+ build(content, prefix=path) # type: ignore
+
+
[email protected]
+def _(content: bytes, path):
+ path.write_bytes(content)
+
+
[email protected]
+def _(content: str, path):
+ path.write_text(content, encoding='utf-8')
+
+
+class Recording:
+ """
+ A TreeMaker object that records everything that would be written.
+
+ >>> r = Recording()
+ >>> build({'foo': {'foo1.txt': 'yes'}, 'bar.txt': 'abc'}, r)
+ >>> r.record
+ ['foo/foo1.txt', 'bar.txt']
+ """
+
+ def __init__(self, loc=pathlib.PurePosixPath(), record=None):
+ self.loc = loc
+ self.record = record if record is not None else []
+
+ def __truediv__(self, other):
+ return Recording(self.loc / other, self.record)
+
+ def write_text(self, content, **kwargs):
+ self.record.append(str(self.loc))
+
+ write_bytes = write_text
+
+ def mkdir(self, **kwargs):
+ return
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/tests/fixtures.py
new/importlib_metadata-6.3.0/tests/fixtures.py
--- old/importlib_metadata-6.1.0/tests/fixtures.py 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/tests/fixtures.py 2023-04-10
04:27:13.000000000 +0200
@@ -11,6 +11,9 @@
from .py39compat import FS_NONASCII
from typing import Dict, Union
+from . import _path
+
+
try:
from importlib import resources # type: ignore
@@ -83,8 +86,10 @@
# Except for python/mypy#731, prefer to define
-# FilesDef = Dict[str, Union['FilesDef', str]]
-FilesDef = Dict[str, Union[Dict[str, Union[Dict[str, str], str]], str]]
+# FilesDef = Dict[str, Union['FilesDef', str, bytes]]
+FilesDef = Dict[
+ str, Union[Dict[str, Union[Dict[str, Union[str, bytes]], str, bytes]],
str, bytes]
+]
class DistInfoPkg(OnSysPath, SiteDir):
@@ -211,6 +216,97 @@
build_files(EggInfoPkg.files, prefix=self.site_dir)
+class EggInfoPkgPipInstalledNoToplevel(OnSysPath, SiteDir):
+ files: FilesDef = {
+ "egg_with_module_pkg.egg-info": {
+ "PKG-INFO": "Name: egg_with_module-pkg",
+ # SOURCES.txt is made from the source archive, and contains files
+ # (setup.py) that are not present after installation.
+ "SOURCES.txt": """
+ egg_with_module.py
+ setup.py
+ egg_with_module_pkg.egg-info/PKG-INFO
+ egg_with_module_pkg.egg-info/SOURCES.txt
+ egg_with_module_pkg.egg-info/top_level.txt
+ """,
+ # installed-files.txt is written by pip, and is a strictly more
+ # accurate source than SOURCES.txt as to the installed contents of
+ # the package.
+ "installed-files.txt": """
+ ../egg_with_module.py
+ PKG-INFO
+ SOURCES.txt
+ top_level.txt
+ """,
+ # missing top_level.txt (to trigger fallback to
installed-files.txt)
+ },
+ "egg_with_module.py": """
+ def main():
+ print("hello world")
+ """,
+ }
+
+ def setUp(self):
+ super().setUp()
+ build_files(EggInfoPkgPipInstalledNoToplevel.files,
prefix=self.site_dir)
+
+
+class EggInfoPkgPipInstalledNoModules(OnSysPath, SiteDir):
+ files: FilesDef = {
+ "egg_with_no_modules_pkg.egg-info": {
+ "PKG-INFO": "Name: egg_with_no_modules-pkg",
+ # SOURCES.txt is made from the source archive, and contains files
+ # (setup.py) that are not present after installation.
+ "SOURCES.txt": """
+ setup.py
+ egg_with_no_modules_pkg.egg-info/PKG-INFO
+ egg_with_no_modules_pkg.egg-info/SOURCES.txt
+ egg_with_no_modules_pkg.egg-info/top_level.txt
+ """,
+ # installed-files.txt is written by pip, and is a strictly more
+ # accurate source than SOURCES.txt as to the installed contents of
+ # the package.
+ "installed-files.txt": """
+ PKG-INFO
+ SOURCES.txt
+ top_level.txt
+ """,
+ # top_level.txt correctly reflects that no modules are installed
+ "top_level.txt": b"\n",
+ },
+ }
+
+ def setUp(self):
+ super().setUp()
+ build_files(EggInfoPkgPipInstalledNoModules.files,
prefix=self.site_dir)
+
+
+class EggInfoPkgSourcesFallback(OnSysPath, SiteDir):
+ files: FilesDef = {
+ "sources_fallback_pkg.egg-info": {
+ "PKG-INFO": "Name: sources_fallback-pkg",
+ # SOURCES.txt is made from the source archive, and contains files
+ # (setup.py) that are not present after installation.
+ "SOURCES.txt": """
+ sources_fallback.py
+ setup.py
+ sources_fallback_pkg.egg-info/PKG-INFO
+ sources_fallback_pkg.egg-info/SOURCES.txt
+ """,
+ # missing installed-files.txt (i.e. not installed by pip) and
+ # missing top_level.txt (to trigger fallback to SOURCES.txt)
+ },
+ "sources_fallback.py": """
+ def main():
+ print("hello world")
+ """,
+ }
+
+ def setUp(self):
+ super().setUp()
+ build_files(EggInfoPkgSourcesFallback.files, prefix=self.site_dir)
+
+
class EggInfoFile(OnSysPath, SiteDir):
files: FilesDef = {
"egginfo_file.egg-info": """
@@ -266,6 +362,16 @@
f.write(DALS(contents))
+def build_record(file_defs):
+ return ''.join(f'{name},,\n' for name in record_names(file_defs))
+
+
+def record_names(file_defs):
+ recording = _path.Recording()
+ _path.build(file_defs, recording)
+ return recording.record
+
+
class FileBuilder:
def unicode_filename(self):
return FS_NONASCII or self.skip("File system does not support
non-ascii.")
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/tests/test_api.py
new/importlib_metadata-6.3.0/tests/test_api.py
--- old/importlib_metadata-6.1.0/tests/test_api.py 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/tests/test_api.py 2023-04-10
04:27:13.000000000 +0200
@@ -27,6 +27,9 @@
class APITests(
fixtures.EggInfoPkg,
+ fixtures.EggInfoPkgPipInstalledNoToplevel,
+ fixtures.EggInfoPkgPipInstalledNoModules,
+ fixtures.EggInfoPkgSourcesFallback,
fixtures.DistInfoPkg,
fixtures.DistInfoPkgWithDot,
fixtures.EggInfoFile,
@@ -62,15 +65,28 @@
distribution(prefix)
def test_for_top_level(self):
- self.assertEqual(
- distribution('egginfo-pkg').read_text('top_level.txt').strip(),
'mod'
- )
+ tests = [
+ ('egginfo-pkg', 'mod'),
+ ('egg_with_no_modules-pkg', ''),
+ ]
+ for pkg_name, expect_content in tests:
+ with self.subTest(pkg_name):
+ self.assertEqual(
+ distribution(pkg_name).read_text('top_level.txt').strip(),
+ expect_content,
+ )
def test_read_text(self):
- top_level = [
- path for path in files('egginfo-pkg') if path.name ==
'top_level.txt'
- ][0]
- self.assertEqual(top_level.read_text(), 'mod\n')
+ tests = [
+ ('egginfo-pkg', 'mod\n'),
+ ('egg_with_no_modules-pkg', '\n'),
+ ]
+ for pkg_name, expect_content in tests:
+ with self.subTest(pkg_name):
+ top_level = [
+ path for path in files(pkg_name) if path.name ==
'top_level.txt'
+ ][0]
+ self.assertEqual(top_level.read_text(), expect_content)
def test_entry_points(self):
eps = entry_points()
@@ -148,6 +164,20 @@
with suppress_known_deprecation():
assert md['does-not-exist'] is None
+ def test_get_key(self):
+ """
+ Getting a key gets the key.
+ """
+ md = metadata('egginfo-pkg')
+ assert md.get('Name') == 'egginfo-pkg'
+
+ def test_get_missing_key(self):
+ """
+ Requesting a missing key will return None.
+ """
+ md = metadata('distinfo-pkg')
+ assert md.get('does-not-exist') is None
+
@staticmethod
def _test_files(files):
root = files[0].root
@@ -170,6 +200,9 @@
def test_files_egg_info(self):
self._test_files(files('egginfo-pkg'))
+ self._test_files(files('egg_with_module-pkg'))
+ self._test_files(files('egg_with_no_modules-pkg'))
+ self._test_files(files('sources_fallback-pkg'))
def test_version_egg_info_file(self):
self.assertEqual(version('egginfo-file'), '0.1')
diff -urN '--exclude=CVS' '--exclude=.cvsignore' '--exclude=.svn'
'--exclude=.svnignore' old/importlib_metadata-6.1.0/tests/test_main.py
new/importlib_metadata-6.3.0/tests/test_main.py
--- old/importlib_metadata-6.1.0/tests/test_main.py 2023-03-18
18:10:20.000000000 +0100
+++ new/importlib_metadata-6.3.0/tests/test_main.py 2023-04-10
04:27:13.000000000 +0200
@@ -3,6 +3,7 @@
import unittest
import importlib
import importlib_metadata
+import itertools
import pyfakefs.fake_filesystem_unittest as ffs
from . import fixtures
@@ -170,11 +171,21 @@
assert meta['Description'] == 'pôrËtend'
-class DiscoveryTests(fixtures.EggInfoPkg, fixtures.DistInfoPkg,
unittest.TestCase):
+class DiscoveryTests(
+ fixtures.EggInfoPkg,
+ fixtures.EggInfoPkgPipInstalledNoToplevel,
+ fixtures.EggInfoPkgPipInstalledNoModules,
+ fixtures.EggInfoPkgSourcesFallback,
+ fixtures.DistInfoPkg,
+ unittest.TestCase,
+):
def test_package_discovery(self):
dists = list(distributions())
assert all(isinstance(dist, Distribution) for dist in dists)
assert any(dist.metadata['Name'] == 'egginfo-pkg' for dist in dists)
+ assert any(dist.metadata['Name'] == 'egg_with_module-pkg' for dist in
dists)
+ assert any(dist.metadata['Name'] == 'egg_with_no_modules-pkg' for dist
in dists)
+ assert any(dist.metadata['Name'] == 'sources_fallback-pkg' for dist in
dists)
assert any(dist.metadata['Name'] == 'distinfo-pkg' for dist in dists)
def test_invalid_usage(self):
@@ -328,28 +339,73 @@
Test top-level modules detected on a package without 'top-level.txt'.
"""
suffixes = importlib.machinery.all_suffixes()
- fixtures.build_files(
- {
- 'all_distributions-1.0.0.dist-info': {
- 'METADATA': """
- Name: all_distributions
- Version: 1.0.0
- """,
- 'RECORD': ''.join(
- f'{i}-top-level{suffix},,\n'
- f'{i}-in-namespace/mod{suffix},,\n'
- f'{i}-in-package/__init__.py,,\n'
- f'{i}-in-package/mod{suffix},,\n'
- for i, suffix in enumerate(suffixes)
- ),
- },
- },
- prefix=self.site_dir,
+ metadata = dict(
+ METADATA="""
+ Name: all_distributions
+ Version: 1.0.0
+ """,
)
+ files = {
+ 'all_distributions-1.0.0.dist-info': metadata,
+ }
+ for i, suffix in enumerate(suffixes):
+ files.update(
+ {
+ f'importable-name {i}{suffix}': '',
+ f'in_namespace_{i}': {
+ f'mod{suffix}': '',
+ },
+ f'in_package_{i}': {
+ '__init__.py': '',
+ f'mod{suffix}': '',
+ },
+ }
+ )
+ metadata.update(RECORD=fixtures.build_record(files))
+ fixtures.build_files(files, prefix=self.site_dir)
distributions = packages_distributions()
for i in range(len(suffixes)):
- assert distributions[f'{i}-top-level'] == ['all_distributions']
- assert distributions[f'{i}-in-namespace'] == ['all_distributions']
- assert distributions[f'{i}-in-package'] == ['all_distributions']
+ assert distributions[f'importable-name {i}'] ==
['all_distributions']
+ assert distributions[f'in_namespace_{i}'] == ['all_distributions']
+ assert distributions[f'in_package_{i}'] == ['all_distributions']
+
+ assert not any(name.endswith('.dist-info') for name in distributions)
+
+
+class PackagesDistributionsEggTest(
+ fixtures.EggInfoPkg,
+ fixtures.EggInfoPkgPipInstalledNoToplevel,
+ fixtures.EggInfoPkgPipInstalledNoModules,
+ fixtures.EggInfoPkgSourcesFallback,
+ unittest.TestCase,
+):
+ def test_packages_distributions_on_eggs(self):
+ """
+ Test old-style egg packages with a variation of 'top_level.txt',
+ 'SOURCES.txt', and 'installed-files.txt', available.
+ """
+ distributions = packages_distributions()
+
+ def import_names_from_package(package_name):
+ return {
+ import_name
+ for import_name, package_names in distributions.items()
+ if package_name in package_names
+ }
+
+ # egginfo-pkg declares one import ('mod') via top_level.txt
+ assert import_names_from_package('egginfo-pkg') == {'mod'}
+
+ # egg_with_module-pkg has one import ('egg_with_module') inferred from
+ # installed-files.txt (top_level.txt is missing)
+ assert import_names_from_package('egg_with_module-pkg') ==
{'egg_with_module'}
+
+ # egg_with_no_modules-pkg should not be associated with any import
names
+ # (top_level.txt is empty, and installed-files.txt has no .py files)
+ assert import_names_from_package('egg_with_no_modules-pkg') == set()
+
+ # sources_fallback-pkg has one import ('sources_fallback') inferred
from
+ # SOURCES.txt (top_level.txt and installed-files.txt is missing)
+ assert import_names_from_package('sources_fallback-pkg') ==
{'sources_fallback'}