Skip to content

Commit 2985efe

Browse files
authored
Merge pull request #6913 from cjerdonek/link-collector-1
Move some PackageFinder methods (preparation for PR #6910)
2 parents 9b9d7b7 + 5e80b82 commit 2985efe

File tree

3 files changed

+172
-165
lines changed

3 files changed

+172
-165
lines changed

src/pip/_internal/index.py

Lines changed: 118 additions & 117 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,65 @@ def _get_html_page(link, session=None):
252252
return None
253253

254254

255+
def group_locations(locations, expand_dir=False):
256+
# type: (Sequence[str], bool) -> Tuple[List[str], List[str]]
257+
"""
258+
Divide a list of locations into two groups: "files" (archives) and "urls."
259+
260+
:return: A pair of lists (files, urls).
261+
"""
262+
files = []
263+
urls = []
264+
265+
# puts the url for the given file path into the appropriate list
266+
def sort_path(path):
267+
url = path_to_url(path)
268+
if mimetypes.guess_type(url, strict=False)[0] == 'text/html':
269+
urls.append(url)
270+
else:
271+
files.append(url)
272+
273+
for url in locations:
274+
275+
is_local_path = os.path.exists(url)
276+
is_file_url = url.startswith('file:')
277+
278+
if is_local_path or is_file_url:
279+
if is_local_path:
280+
path = url
281+
else:
282+
path = url_to_path(url)
283+
if os.path.isdir(path):
284+
if expand_dir:
285+
path = os.path.realpath(path)
286+
for item in os.listdir(path):
287+
sort_path(os.path.join(path, item))
288+
elif is_file_url:
289+
urls.append(url)
290+
else:
291+
logger.warning(
292+
"Path '{0}' is ignored: "
293+
"it is a directory.".format(path),
294+
)
295+
elif os.path.isfile(path):
296+
sort_path(path)
297+
else:
298+
logger.warning(
299+
"Url '%s' is ignored: it is neither a file "
300+
"nor a directory.", url,
301+
)
302+
elif is_url(url):
303+
# Only add url with clear scheme
304+
urls.append(url)
305+
else:
306+
logger.warning(
307+
"Url '%s' is ignored. It is either a non-existing "
308+
"path or lacks a specific scheme.", url,
309+
)
310+
311+
return files, urls
312+
313+
255314
def _check_link_requires_python(
256315
link, # type: Link
257316
version_info, # type: Tuple[int, int, int]
@@ -899,64 +958,6 @@ def set_allow_all_prereleases(self):
899958
# type: () -> None
900959
self._candidate_prefs.allow_all_prereleases = True
901960

902-
@staticmethod
903-
def _sort_locations(locations, expand_dir=False):
904-
# type: (Sequence[str], bool) -> Tuple[List[str], List[str]]
905-
"""
906-
Sort locations into "files" (archives) and "urls", and return
907-
a pair of lists (files,urls)
908-
"""
909-
files = []
910-
urls = []
911-
912-
# puts the url for the given file path into the appropriate list
913-
def sort_path(path):
914-
url = path_to_url(path)
915-
if mimetypes.guess_type(url, strict=False)[0] == 'text/html':
916-
urls.append(url)
917-
else:
918-
files.append(url)
919-
920-
for url in locations:
921-
922-
is_local_path = os.path.exists(url)
923-
is_file_url = url.startswith('file:')
924-
925-
if is_local_path or is_file_url:
926-
if is_local_path:
927-
path = url
928-
else:
929-
path = url_to_path(url)
930-
if os.path.isdir(path):
931-
if expand_dir:
932-
path = os.path.realpath(path)
933-
for item in os.listdir(path):
934-
sort_path(os.path.join(path, item))
935-
elif is_file_url:
936-
urls.append(url)
937-
else:
938-
logger.warning(
939-
"Path '{0}' is ignored: "
940-
"it is a directory.".format(path),
941-
)
942-
elif os.path.isfile(path):
943-
sort_path(path)
944-
else:
945-
logger.warning(
946-
"Url '%s' is ignored: it is neither a file "
947-
"nor a directory.", url,
948-
)
949-
elif is_url(url):
950-
# Only add url with clear scheme
951-
urls.append(url)
952-
else:
953-
logger.warning(
954-
"Url '%s' is ignored. It is either a non-existing "
955-
"path or lacks a specific scheme.", url,
956-
)
957-
958-
return files, urls
959-
960961
def make_link_evaluator(self, project_name):
961962
# type: (str) -> LinkEvaluator
962963
canonical_name = canonicalize_name(project_name)
@@ -971,6 +972,63 @@ def make_link_evaluator(self, project_name):
971972
ignore_requires_python=self._ignore_requires_python,
972973
)
973974

975+
def _sort_links(self, links):
976+
# type: (Iterable[Link]) -> List[Link]
977+
"""
978+
Returns elements of links in order, non-egg links first, egg links
979+
second, while eliminating duplicates
980+
"""
981+
eggs, no_eggs = [], []
982+
seen = set() # type: Set[Link]
983+
for link in links:
984+
if link not in seen:
985+
seen.add(link)
986+
if link.egg_fragment:
987+
eggs.append(link)
988+
else:
989+
no_eggs.append(link)
990+
return no_eggs + eggs
991+
992+
def _log_skipped_link(self, link, reason):
993+
# type: (Link, Text) -> None
994+
if link not in self._logged_links:
995+
# Mark this as a unicode string to prevent "UnicodeEncodeError:
996+
# 'ascii' codec can't encode character" in Python 2 when
997+
# the reason contains non-ascii characters.
998+
# Also, put the link at the end so the reason is more visible
999+
# and because the link string is usually very long.
1000+
logger.debug(u'Skipping link: %s: %s', reason, link)
1001+
self._logged_links.add(link)
1002+
1003+
def get_install_candidate(self, link_evaluator, link):
1004+
# type: (LinkEvaluator, Link) -> Optional[InstallationCandidate]
1005+
"""
1006+
If the link is a candidate for install, convert it to an
1007+
InstallationCandidate and return it. Otherwise, return None.
1008+
"""
1009+
is_candidate, result = link_evaluator.evaluate_link(link)
1010+
if not is_candidate:
1011+
if result:
1012+
self._log_skipped_link(link, reason=result)
1013+
return None
1014+
1015+
return InstallationCandidate(
1016+
project=link_evaluator.project_name,
1017+
link=link,
1018+
# Convert the Text result to str since InstallationCandidate
1019+
# accepts str.
1020+
version=str(result),
1021+
)
1022+
1023+
def _package_versions(self, link_evaluator, links):
1024+
# type: (LinkEvaluator, Iterable[Link]) -> List[InstallationCandidate]
1025+
result = []
1026+
for link in self._sort_links(links):
1027+
candidate = self.get_install_candidate(link_evaluator, link)
1028+
if candidate is not None:
1029+
result.append(candidate)
1030+
return result
1031+
9741032
def find_all_candidates(self, project_name):
9751033
# type: (str) -> List[InstallationCandidate]
9761034
"""Find all available InstallationCandidate for project_name
@@ -983,8 +1041,8 @@ def find_all_candidates(self, project_name):
9831041
"""
9841042
search_scope = self.search_scope
9851043
index_locations = search_scope.get_index_urls_locations(project_name)
986-
index_file_loc, index_url_loc = self._sort_locations(index_locations)
987-
fl_file_loc, fl_url_loc = self._sort_locations(
1044+
index_file_loc, index_url_loc = group_locations(index_locations)
1045+
fl_file_loc, fl_url_loc = group_locations(
9881046
self.find_links, expand_dir=True,
9891047
)
9901048

@@ -1177,63 +1235,6 @@ def _get_pages(self, locations, project_name):
11771235

11781236
yield page
11791237

1180-
def _sort_links(self, links):
1181-
# type: (Iterable[Link]) -> List[Link]
1182-
"""
1183-
Returns elements of links in order, non-egg links first, egg links
1184-
second, while eliminating duplicates
1185-
"""
1186-
eggs, no_eggs = [], []
1187-
seen = set() # type: Set[Link]
1188-
for link in links:
1189-
if link not in seen:
1190-
seen.add(link)
1191-
if link.egg_fragment:
1192-
eggs.append(link)
1193-
else:
1194-
no_eggs.append(link)
1195-
return no_eggs + eggs
1196-
1197-
def _log_skipped_link(self, link, reason):
1198-
# type: (Link, Text) -> None
1199-
if link not in self._logged_links:
1200-
# Mark this as a unicode string to prevent "UnicodeEncodeError:
1201-
# 'ascii' codec can't encode character" in Python 2 when
1202-
# the reason contains non-ascii characters.
1203-
# Also, put the link at the end so the reason is more visible
1204-
# and because the link string is usually very long.
1205-
logger.debug(u'Skipping link: %s: %s', reason, link)
1206-
self._logged_links.add(link)
1207-
1208-
def get_install_candidate(self, link_evaluator, link):
1209-
# type: (LinkEvaluator, Link) -> Optional[InstallationCandidate]
1210-
"""
1211-
If the link is a candidate for install, convert it to an
1212-
InstallationCandidate and return it. Otherwise, return None.
1213-
"""
1214-
is_candidate, result = link_evaluator.evaluate_link(link)
1215-
if not is_candidate:
1216-
if result:
1217-
self._log_skipped_link(link, reason=result)
1218-
return None
1219-
1220-
return InstallationCandidate(
1221-
project=link_evaluator.project_name,
1222-
link=link,
1223-
# Convert the Text result to str since InstallationCandidate
1224-
# accepts str.
1225-
version=str(result),
1226-
)
1227-
1228-
def _package_versions(self, link_evaluator, links):
1229-
# type: (LinkEvaluator, Iterable[Link]) -> List[InstallationCandidate]
1230-
result = []
1231-
for link in self._sort_links(links):
1232-
candidate = self.get_install_candidate(link_evaluator, link)
1233-
if candidate is not None:
1234-
result.append(candidate)
1235-
return result
1236-
12371238

12381239
def _find_name_version_sep(fragment, canonical_name):
12391240
# type: (str, str) -> int

0 commit comments

Comments
 (0)