Repository: pypa/pip

Issue:
`pip show --files` broke for wheel installs
`pip show --files` was written to look for `installed-files.txt` which isn't present for wheels.



Discussion:

Resolving patch:
diff --git a/pip/commands/show.py b/pip/commands/show.py
--- a/pip/commands/show.py
+++ b/pip/commands/show.py
@@ -40,26 +40,32 @@ def search_packages_info(query):
     pip generated 'installed-files.txt' in the distributions '.egg-info'
     directory.
     """
-    installed_packages = dict(
+    installed = dict(
         [(p.project_name.lower(), p) for p in pkg_resources.working_set])
-    for name in query:
-        normalized_name = name.lower()
-        if normalized_name in installed_packages:
-            dist = installed_packages[normalized_name]
-            package = {
-                'name': dist.project_name,
-                'version': dist.version,
-                'location': dist.location,
-                'requires': [dep.project_name for dep in dist.requires()],
-            }
-            filelist = os.path.join(
-                dist.location,
-                dist.egg_name() + '.egg-info',
-                'installed-files.txt',
-            )
-            if os.path.isfile(filelist):
-                package['files'] = filelist
-            yield package
+    query_names = [name.lower() for name in query]
+    for dist in [installed[pkg] for pkg in query_names if pkg in installed]:
+        package = {
+            'name': dist.project_name,
+            'version': dist.version,
+            'location': dist.location,
+            'requires': [dep.project_name for dep in dist.requires()],
+        }
+        file_list = None
+        if isinstance(dist, pkg_resources.DistInfoDistribution):
+            # RECORDs should be part of .dist-info metadatas
+            if dist.has_metadata('RECORD'):
+                lines = dist.get_metadata_lines('RECORD')
+                paths = [l.split(',')[0] for l in lines]
+                paths = [os.path.join(dist.location, p) for p in paths]
+                file_list = [os.path.relpath(p, dist.egg_info)
+                             for p in paths]
+        else:
+            # Otherwise use pip's log for .egg-info's
+            if dist.has_metadata('installed-files.txt'):
+                file_list = dist.get_metadata_lines('installed-files.txt')
+        # use and short-circuit to check for None
+        package['files'] = file_list and sorted(file_list)
+        yield package
 
 
 def print_results(distributions, list_all_files):
@@ -74,8 +80,8 @@ def print_results(distributions, list_all_files):
         logger.notify("Requires: %s" % ', '.join(dist['requires']))
         if list_all_files:
             logger.notify("Files:")
-            if 'files' in dist:
-                for line in open(dist['files']):
+            if dist['files'] is not None:
+                for line in dist['files']:
                     logger.notify("  %s" % line.strip())
             else:
                 logger.notify("Cannot locate installed-files.txt")


Test patch:
diff --git a/tests/functional/test_show.py b/tests/functional/test_show.py
--- a/tests/functional/test_show.py
+++ b/tests/functional/test_show.py
@@ -17,29 +17,46 @@ def test_show(script):
     assert lines[4] == 'Requires: '
 
 
-def test_show_with_files_not_found(script):
+def test_show_with_files_not_found(script, data):
     """
     Test for show command with installed files listing enabled and
     installed-files.txt not found.
     """
-    result = script.pip('show', '-f', 'pip')
+    editable = data.packages.join('SetupPyUTF8')
+    script.pip('install', '-e', editable)
+    result = script.pip('show', '-f', 'SetupPyUTF8')
     lines = result.stdout.split('\n')
     assert len(lines) == 8
     assert lines[0] == '---', lines[0]
-    assert lines[1] == 'Name: pip', lines[1]
-    assert lines[2] == 'Version: %s' % __version__, lines[2]
+    assert lines[1] == 'Name: SetupPyUTF8', lines[1]
+    assert lines[2] == 'Version: 0.0.0', lines[2]
     assert lines[3].startswith('Location: '), lines[3]
-    assert lines[4] == 'Requires: '
-    assert lines[5] == 'Files:', lines[4]
-    assert lines[6] == 'Cannot locate installed-files.txt', lines[5]
+    assert lines[4] == 'Requires: ', lines[4]
+    assert lines[5] == 'Files:', lines[5]
+    assert lines[6] == 'Cannot locate installed-files.txt', lines[6]
+
+
+def test_show_with_files_from_wheel(script, data):
+    """
+    Test that a wheel's files can be listed
+    """
+    wheel_file = data.packages.join('simple.dist-0.1-py2.py3-none-any.whl')
+    script.pip('install', '--no-index', wheel_file)
+    result = script.pip('show', '-f', 'simple.dist')
+    lines = result.stdout.split('\n')
+    assert lines[1] == 'Name: simple.dist', lines[1]
+    assert 'Cannot locate installed-files.txt' not in lines[6], lines[6]
+    assert re.search(r"Files:\n(  .+\n)+", result.stdout)
 
 
 def test_show_with_all_files(script):
     """
     Test listing all files in the show command.
     """
-    result = script.pip('install', 'initools==0.2')
+    script.pip('install', 'initools==0.2')
     result = script.pip('show', '--files', 'initools')
+    lines = result.stdout.split('\n')
+    assert 'Cannot locate installed-files.txt' not in lines[6], lines[6]
     assert re.search(r"Files:\n(  .+\n)+", result.stdout)