@@ -252,6 +252,65 @@ def _get_html_page(link, session=None):
252
252
return None
253
253
254
254
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
+
255
314
def _check_link_requires_python (
256
315
link , # type: Link
257
316
version_info , # type: Tuple[int, int, int]
@@ -899,64 +958,6 @@ def set_allow_all_prereleases(self):
899
958
# type: () -> None
900
959
self ._candidate_prefs .allow_all_prereleases = True
901
960
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
-
960
961
def make_link_evaluator (self , project_name ):
961
962
# type: (str) -> LinkEvaluator
962
963
canonical_name = canonicalize_name (project_name )
@@ -971,6 +972,63 @@ def make_link_evaluator(self, project_name):
971
972
ignore_requires_python = self ._ignore_requires_python ,
972
973
)
973
974
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
+
974
1032
def find_all_candidates (self , project_name ):
975
1033
# type: (str) -> List[InstallationCandidate]
976
1034
"""Find all available InstallationCandidate for project_name
@@ -983,8 +1041,8 @@ def find_all_candidates(self, project_name):
983
1041
"""
984
1042
search_scope = self .search_scope
985
1043
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 (
988
1046
self .find_links , expand_dir = True ,
989
1047
)
990
1048
@@ -1177,63 +1235,6 @@ def _get_pages(self, locations, project_name):
1177
1235
1178
1236
yield page
1179
1237
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
-
1237
1238
1238
1239
def _find_name_version_sep (fragment , canonical_name ):
1239
1240
# type: (str, str) -> int
0 commit comments