Spaces:
Runtime error
Runtime error
import itertools | |
import logging | |
import os | |
import posixpath | |
import urllib.parse | |
from typing import List | |
from pip._vendor.packaging.utils import canonicalize_name | |
from pip._internal.models.index import PyPI | |
from pip._internal.utils.compat import has_tls | |
from pip._internal.utils.misc import normalize_path, redact_auth_from_url | |
logger = logging.getLogger(__name__) | |
class SearchScope: | |
""" | |
Encapsulates the locations that pip is configured to search. | |
""" | |
__slots__ = ["find_links", "index_urls", "no_index"] | |
def create( | |
cls, | |
find_links: List[str], | |
index_urls: List[str], | |
no_index: bool, | |
) -> "SearchScope": | |
""" | |
Create a SearchScope object after normalizing the `find_links`. | |
""" | |
# Build find_links. If an argument starts with ~, it may be | |
# a local file relative to a home directory. So try normalizing | |
# it and if it exists, use the normalized version. | |
# This is deliberately conservative - it might be fine just to | |
# blindly normalize anything starting with a ~... | |
built_find_links: List[str] = [] | |
for link in find_links: | |
if link.startswith("~"): | |
new_link = normalize_path(link) | |
if os.path.exists(new_link): | |
link = new_link | |
built_find_links.append(link) | |
# If we don't have TLS enabled, then WARN if anyplace we're looking | |
# relies on TLS. | |
if not has_tls(): | |
for link in itertools.chain(index_urls, built_find_links): | |
parsed = urllib.parse.urlparse(link) | |
if parsed.scheme == "https": | |
logger.warning( | |
"pip is configured with locations that require " | |
"TLS/SSL, however the ssl module in Python is not " | |
"available." | |
) | |
break | |
return cls( | |
find_links=built_find_links, | |
index_urls=index_urls, | |
no_index=no_index, | |
) | |
def __init__( | |
self, | |
find_links: List[str], | |
index_urls: List[str], | |
no_index: bool, | |
) -> None: | |
self.find_links = find_links | |
self.index_urls = index_urls | |
self.no_index = no_index | |
def get_formatted_locations(self) -> str: | |
lines = [] | |
redacted_index_urls = [] | |
if self.index_urls and self.index_urls != [PyPI.simple_url]: | |
for url in self.index_urls: | |
redacted_index_url = redact_auth_from_url(url) | |
# Parse the URL | |
purl = urllib.parse.urlsplit(redacted_index_url) | |
# URL is generally invalid if scheme and netloc is missing | |
# there are issues with Python and URL parsing, so this test | |
# is a bit crude. See bpo-20271, bpo-23505. Python doesn't | |
# always parse invalid URLs correctly - it should raise | |
# exceptions for malformed URLs | |
if not purl.scheme and not purl.netloc: | |
logger.warning( | |
'The index url "%s" seems invalid, please provide a scheme.', | |
redacted_index_url, | |
) | |
redacted_index_urls.append(redacted_index_url) | |
lines.append( | |
"Looking in indexes: {}".format(", ".join(redacted_index_urls)) | |
) | |
if self.find_links: | |
lines.append( | |
"Looking in links: {}".format( | |
", ".join(redact_auth_from_url(url) for url in self.find_links) | |
) | |
) | |
return "\n".join(lines) | |
def get_index_urls_locations(self, project_name: str) -> List[str]: | |
"""Returns the locations found via self.index_urls | |
Checks the url_name on the main (first in the list) index and | |
use this url_name to produce all locations | |
""" | |
def mkurl_pypi_url(url: str) -> str: | |
loc = posixpath.join( | |
url, urllib.parse.quote(canonicalize_name(project_name)) | |
) | |
# For maximum compatibility with easy_install, ensure the path | |
# ends in a trailing slash. Although this isn't in the spec | |
# (and PyPI can handle it without the slash) some other index | |
# implementations might break if they relied on easy_install's | |
# behavior. | |
if not loc.endswith("/"): | |
loc = loc + "/" | |
return loc | |
return [mkurl_pypi_url(url) for url in self.index_urls] | |