diff env/lib/python3.9/site-packages/pip/_internal/commands/show.py @ 0:4f3585e2f14b draft default tip

"planemo upload commit 60cee0fc7c0cda8592644e1aad72851dec82c959"
author shellac
date Mon, 22 Mar 2021 18:12:50 +0000
parents
children
line wrap: on
line diff
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/env/lib/python3.9/site-packages/pip/_internal/commands/show.py	Mon Mar 22 18:12:50 2021 +0000
@@ -0,0 +1,184 @@
+import logging
+import os
+from email.parser import FeedParser
+
+from pip._vendor import pkg_resources
+from pip._vendor.packaging.utils import canonicalize_name
+
+from pip._internal.cli.base_command import Command
+from pip._internal.cli.status_codes import ERROR, SUCCESS
+from pip._internal.utils.misc import write_output
+from pip._internal.utils.typing import MYPY_CHECK_RUNNING
+
+if MYPY_CHECK_RUNNING:
+    from optparse import Values
+    from typing import Dict, Iterator, List
+
+logger = logging.getLogger(__name__)
+
+
+class ShowCommand(Command):
+    """
+    Show information about one or more installed packages.
+
+    The output is in RFC-compliant mail header format.
+    """
+
+    usage = """
+      %prog [options] <package> ..."""
+    ignore_require_venv = True
+
+    def add_options(self):
+        # type: () -> None
+        self.cmd_opts.add_option(
+            '-f', '--files',
+            dest='files',
+            action='store_true',
+            default=False,
+            help='Show the full list of installed files for each package.')
+
+        self.parser.insert_option_group(0, self.cmd_opts)
+
+    def run(self, options, args):
+        # type: (Values, List[str]) -> int
+        if not args:
+            logger.warning('ERROR: Please provide a package name or names.')
+            return ERROR
+        query = args
+
+        results = search_packages_info(query)
+        if not print_results(
+                results, list_files=options.files, verbose=options.verbose):
+            return ERROR
+        return SUCCESS
+
+
+def search_packages_info(query):
+    # type: (List[str]) -> Iterator[Dict[str, str]]
+    """
+    Gather details from installed distributions. Print distribution name,
+    version, location, and installed files. Installed files requires a
+    pip generated 'installed-files.txt' in the distributions '.egg-info'
+    directory.
+    """
+    installed = {}
+    for p in pkg_resources.working_set:
+        installed[canonicalize_name(p.project_name)] = p
+
+    query_names = [canonicalize_name(name) for name in query]
+    missing = sorted(
+        [name for name, pkg in zip(query, query_names) if pkg not in installed]
+    )
+    if missing:
+        logger.warning('Package(s) not found: %s', ', '.join(missing))
+
+    def get_requiring_packages(package_name):
+        # type: (str) -> List[str]
+        canonical_name = canonicalize_name(package_name)
+        return [
+            pkg.project_name for pkg in pkg_resources.working_set
+            if canonical_name in
+               [canonicalize_name(required.name) for required in
+                pkg.requires()]
+        ]
+
+    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()],
+            'required_by': get_requiring_packages(dist.project_name)
+        }
+        file_list = None
+        metadata = ''
+        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 = [line.split(',')[0] for line in lines]
+                paths = [os.path.join(dist.location, p) for p in paths]
+                file_list = [os.path.relpath(p, dist.location) for p in paths]
+
+            if dist.has_metadata('METADATA'):
+                metadata = dist.get_metadata('METADATA')
+        else:
+            # Otherwise use pip's log for .egg-info's
+            if dist.has_metadata('installed-files.txt'):
+                paths = dist.get_metadata_lines('installed-files.txt')
+                paths = [os.path.join(dist.egg_info, p) for p in paths]
+                file_list = [os.path.relpath(p, dist.location) for p in paths]
+
+            if dist.has_metadata('PKG-INFO'):
+                metadata = dist.get_metadata('PKG-INFO')
+
+        if dist.has_metadata('entry_points.txt'):
+            entry_points = dist.get_metadata_lines('entry_points.txt')
+            package['entry_points'] = entry_points
+
+        if dist.has_metadata('INSTALLER'):
+            for line in dist.get_metadata_lines('INSTALLER'):
+                if line.strip():
+                    package['installer'] = line.strip()
+                    break
+
+        # @todo: Should pkg_resources.Distribution have a
+        # `get_pkg_info` method?
+        feed_parser = FeedParser()
+        feed_parser.feed(metadata)
+        pkg_info_dict = feed_parser.close()
+        for key in ('metadata-version', 'summary',
+                    'home-page', 'author', 'author-email', 'license'):
+            package[key] = pkg_info_dict.get(key)
+
+        # It looks like FeedParser cannot deal with repeated headers
+        classifiers = []
+        for line in metadata.splitlines():
+            if line.startswith('Classifier: '):
+                classifiers.append(line[len('Classifier: '):])
+        package['classifiers'] = classifiers
+
+        if file_list:
+            package['files'] = sorted(file_list)
+        yield package
+
+
+def print_results(distributions, list_files=False, verbose=False):
+    # type: (Iterator[Dict[str, str]], bool, bool) -> bool
+    """
+    Print the information from installed distributions found.
+    """
+    results_printed = False
+    for i, dist in enumerate(distributions):
+        results_printed = True
+        if i > 0:
+            write_output("---")
+
+        write_output("Name: %s", dist.get('name', ''))
+        write_output("Version: %s", dist.get('version', ''))
+        write_output("Summary: %s", dist.get('summary', ''))
+        write_output("Home-page: %s", dist.get('home-page', ''))
+        write_output("Author: %s", dist.get('author', ''))
+        write_output("Author-email: %s", dist.get('author-email', ''))
+        write_output("License: %s", dist.get('license', ''))
+        write_output("Location: %s", dist.get('location', ''))
+        write_output("Requires: %s", ', '.join(dist.get('requires', [])))
+        write_output("Required-by: %s", ', '.join(dist.get('required_by', [])))
+
+        if verbose:
+            write_output("Metadata-Version: %s",
+                         dist.get('metadata-version', ''))
+            write_output("Installer: %s", dist.get('installer', ''))
+            write_output("Classifiers:")
+            for classifier in dist.get('classifiers', []):
+                write_output("  %s", classifier)
+            write_output("Entry-points:")
+            for entry in dist.get('entry_points', []):
+                write_output("  %s", entry.strip())
+        if list_files:
+            write_output("Files:")
+            for line in dist.get('files', []):
+                write_output("  %s", line.strip())
+            if "files" not in dist:
+                write_output("Cannot locate installed-files.txt")
+    return results_printed