Coverage for /pythoncovmergedfiles/medio/medio/usr/local/lib/python3.8/site-packages/pip/_internal/models/search_scope.py: 33%
54 statements
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
« prev ^ index » next coverage.py v7.2.7, created at 2023-06-07 06:48 +0000
1import itertools
2import logging
3import os
4import posixpath
5import urllib.parse
6from typing import List
8from pip._vendor.packaging.utils import canonicalize_name
10from pip._internal.models.index import PyPI
11from pip._internal.utils.compat import has_tls
12from pip._internal.utils.misc import normalize_path, redact_auth_from_url
14logger = logging.getLogger(__name__)
17class SearchScope:
19 """
20 Encapsulates the locations that pip is configured to search.
21 """
23 __slots__ = ["find_links", "index_urls", "no_index"]
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)
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
61 return cls(
62 find_links=built_find_links,
63 index_urls=index_urls,
64 no_index=no_index,
65 )
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
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)
84 # Parse the URL
85 purl = urllib.parse.urlsplit(redacted_index_url)
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 )
98 redacted_index_urls.append(redacted_index_url)
100 lines.append(
101 "Looking in indexes: {}".format(", ".join(redacted_index_urls))
102 )
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)
112 def get_index_urls_locations(self, project_name: str) -> List[str]:
113 """Returns the locations found via self.index_urls
115 Checks the url_name on the main (first in the list) index and
116 use this url_name to produce all locations
117 """
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
132 return [mkurl_pypi_url(url) for url in self.index_urls]