python (3.11.7)

(root)/
lib/
python3.11/
site-packages/
pip/
_internal/
models/
search_scope.py
       1  import itertools
       2  import logging
       3  import os
       4  import posixpath
       5  import urllib.parse
       6  from typing import List
       7  
       8  from pip._vendor.packaging.utils import canonicalize_name
       9  
      10  from pip._internal.models.index import PyPI
      11  from pip._internal.utils.compat import has_tls
      12  from pip._internal.utils.misc import normalize_path, redact_auth_from_url
      13  
      14  logger = logging.getLogger(__name__)
      15  
      16  
      17  class ESC[4;38;5;81mSearchScope:
      18  
      19      """
      20      Encapsulates the locations that pip is configured to search.
      21      """
      22  
      23      __slots__ = ["find_links", "index_urls", "no_index"]
      24  
      25      @classmethod
      26      def create(
      27          cls,
      28          find_links: List[str],
      29          index_urls: List[str],
      30          no_index: bool,
      31      ) -> "SearchScope":
      32          """
      33          Create a SearchScope object after normalizing the `find_links`.
      34          """
      35          # Build find_links. If an argument starts with ~, it may be
      36          # a local file relative to a home directory. So try normalizing
      37          # it and if it exists, use the normalized version.
      38          # This is deliberately conservative - it might be fine just to
      39          # blindly normalize anything starting with a ~...
      40          built_find_links: List[str] = []
      41          for link in find_links:
      42              if link.startswith("~"):
      43                  new_link = normalize_path(link)
      44                  if os.path.exists(new_link):
      45                      link = new_link
      46              built_find_links.append(link)
      47  
      48          # If we don't have TLS enabled, then WARN if anyplace we're looking
      49          # relies on TLS.
      50          if not has_tls():
      51              for link in itertools.chain(index_urls, built_find_links):
      52                  parsed = urllib.parse.urlparse(link)
      53                  if parsed.scheme == "https":
      54                      logger.warning(
      55                          "pip is configured with locations that require "
      56                          "TLS/SSL, however the ssl module in Python is not "
      57                          "available."
      58                      )
      59                      break
      60  
      61          return cls(
      62              find_links=built_find_links,
      63              index_urls=index_urls,
      64              no_index=no_index,
      65          )
      66  
      67      def __init__(
      68          self,
      69          find_links: List[str],
      70          index_urls: List[str],
      71          no_index: bool,
      72      ) -> None:
      73          self.find_links = find_links
      74          self.index_urls = index_urls
      75          self.no_index = no_index
      76  
      77      def get_formatted_locations(self) -> str:
      78          lines = []
      79          redacted_index_urls = []
      80          if self.index_urls and self.index_urls != [PyPI.simple_url]:
      81              for url in self.index_urls:
      82                  redacted_index_url = redact_auth_from_url(url)
      83  
      84                  # Parse the URL
      85                  purl = urllib.parse.urlsplit(redacted_index_url)
      86  
      87                  # URL is generally invalid if scheme and netloc is missing
      88                  # there are issues with Python and URL parsing, so this test
      89                  # is a bit crude. See bpo-20271, bpo-23505. Python doesn't
      90                  # always parse invalid URLs correctly - it should raise
      91                  # exceptions for malformed URLs
      92                  if not purl.scheme and not purl.netloc:
      93                      logger.warning(
      94                          'The index url "%s" seems invalid, please provide a scheme.',
      95                          redacted_index_url,
      96                      )
      97  
      98                  redacted_index_urls.append(redacted_index_url)
      99  
     100              lines.append(
     101                  "Looking in indexes: {}".format(", ".join(redacted_index_urls))
     102              )
     103  
     104          if self.find_links:
     105              lines.append(
     106                  "Looking in links: {}".format(
     107                      ", ".join(redact_auth_from_url(url) for url in self.find_links)
     108                  )
     109              )
     110          return "\n".join(lines)
     111  
     112      def get_index_urls_locations(self, project_name: str) -> List[str]:
     113          """Returns the locations found via self.index_urls
     114  
     115          Checks the url_name on the main (first in the list) index and
     116          use this url_name to produce all locations
     117          """
     118  
     119          def mkurl_pypi_url(url: str) -> str:
     120              loc = posixpath.join(
     121                  url, urllib.parse.quote(canonicalize_name(project_name))
     122              )
     123              # For maximum compatibility with easy_install, ensure the path
     124              # ends in a trailing slash.  Although this isn't in the spec
     125              # (and PyPI can handle it without the slash) some other index
     126              # implementations might break if they relied on easy_install's
     127              # behavior.
     128              if not loc.endswith("/"):
     129                  loc = loc + "/"
     130              return loc
     131  
     132          return [mkurl_pypi_url(url) for url in self.index_urls]