python (3.11.7)
       1  import hashlib
       2  import logging
       3  import sys
       4  from optparse import Values
       5  from typing import List
       6  
       7  from pip._internal.cli.base_command import Command
       8  from pip._internal.cli.status_codes import ERROR, SUCCESS
       9  from pip._internal.utils.hashes import FAVORITE_HASH, STRONG_HASHES
      10  from pip._internal.utils.misc import read_chunks, write_output
      11  
      12  logger = logging.getLogger(__name__)
      13  
      14  
      15  class ESC[4;38;5;81mHashCommand(ESC[4;38;5;149mCommand):
      16      """
      17      Compute a hash of a local package archive.
      18  
      19      These can be used with --hash in a requirements file to do repeatable
      20      installs.
      21      """
      22  
      23      usage = "%prog [options] <file> ..."
      24      ignore_require_venv = True
      25  
      26      def add_options(self) -> None:
      27          self.cmd_opts.add_option(
      28              "-a",
      29              "--algorithm",
      30              dest="algorithm",
      31              choices=STRONG_HASHES,
      32              action="store",
      33              default=FAVORITE_HASH,
      34              help="The hash algorithm to use: one of {}".format(
      35                  ", ".join(STRONG_HASHES)
      36              ),
      37          )
      38          self.parser.insert_option_group(0, self.cmd_opts)
      39  
      40      def run(self, options: Values, args: List[str]) -> int:
      41          if not args:
      42              self.parser.print_usage(sys.stderr)
      43              return ERROR
      44  
      45          algorithm = options.algorithm
      46          for path in args:
      47              write_output(
      48                  "%s:\n--hash=%s:%s", path, algorithm, _hash_of_file(path, algorithm)
      49              )
      50          return SUCCESS
      51  
      52  
      53  def _hash_of_file(path: str, algorithm: str) -> str:
      54      """Return the hash digest of a file."""
      55      with open(path, "rb") as archive:
      56          hash = hashlib.new(algorithm)
      57          for chunk in read_chunks(archive):
      58              hash.update(chunk)
      59      return hash.hexdigest()