From f4480669d3d0e9046a11313e5c3bcbb92e7f70a4 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Tue, 29 Jun 2021 11:35:51 -0500 Subject: [PATCH 01/10] Complete type annotations in `pip/_internal/index` Convert type hint commentaries into annotations for `pip/_internal/index` --- src/pip/_internal/index/collector.py | 110 ++++++++++----------------- 1 file changed, 41 insertions(+), 69 deletions(-) diff --git a/src/pip/_internal/index/collector.py b/src/pip/_internal/index/collector.py index 0721e3683f9..a0846baba83 100644 --- a/src/pip/_internal/index/collector.py +++ b/src/pip/_internal/index/collector.py @@ -46,8 +46,7 @@ ResponseHeaders = MutableMapping[str, str] -def _match_vcs_scheme(url): - # type: (str) -> Optional[str] +def _match_vcs_scheme(url: str) -> Optional[str]: """Look for VCS schemes in the URL. Returns the matched VCS scheme, or None if there's no match. @@ -59,15 +58,13 @@ def _match_vcs_scheme(url): class _NotHTML(Exception): - def __init__(self, content_type, request_desc): - # type: (str, str) -> None + def __init__(self, content_type: str, request_desc: str) -> None: super().__init__(content_type, request_desc) self.content_type = content_type self.request_desc = request_desc -def _ensure_html_header(response): - # type: (Response) -> None +def _ensure_html_header(response: Response) -> None: """Check the Content-Type header to ensure the response contains HTML. Raises `_NotHTML` if the content type is not text/html. @@ -81,8 +78,7 @@ class _NotHTTP(Exception): pass -def _ensure_html_response(url, session): - # type: (str, PipSession) -> None +def _ensure_html_response(url: str, session: PipSession) -> None: """Send a HEAD request to the URL, and ensure the response contains HTML. Raises `_NotHTTP` if the URL is not available for a HEAD request, or @@ -98,8 +94,7 @@ def _ensure_html_response(url, session): _ensure_html_header(resp) -def _get_html_response(url, session): - # type: (str, PipSession) -> Response +def _get_html_response(url: str, session: PipSession) -> Response: """Access an HTML page with GET, and return the response. This consists of three parts: @@ -149,8 +144,7 @@ def _get_html_response(url, session): return resp -def _get_encoding_from_headers(headers): - # type: (ResponseHeaders) -> Optional[str] +def _get_encoding_from_headers(headers: ResponseHeaders) -> Optional[str]: """Determine if we have any encoding information in our headers. """ if headers and "Content-Type" in headers: @@ -160,8 +154,7 @@ def _get_encoding_from_headers(headers): return None -def _determine_base_url(document, page_url): - # type: (HTMLElement, str) -> str +def _determine_base_url(document: HTMLElement, page_url: str) -> str: """Determine the HTML document's base URL. This looks for a ```` tag in the HTML document. If present, its href @@ -180,8 +173,7 @@ def _determine_base_url(document, page_url): return page_url -def _clean_url_path_part(part): - # type: (str) -> str +def _clean_url_path_part(part: str) -> str: """ Clean a "part" of a URL path (i.e. after splitting on "@" characters). """ @@ -189,8 +181,7 @@ def _clean_url_path_part(part): return urllib.parse.quote(urllib.parse.unquote(part)) -def _clean_file_url_path(part): - # type: (str) -> str +def _clean_file_url_path(part: str) -> str: """ Clean the first part of a URL path that corresponds to a local filesystem path (i.e. the first part after splitting on "@" characters). @@ -207,8 +198,7 @@ def _clean_file_url_path(part): _reserved_chars_re = re.compile('(@|%2F)', re.IGNORECASE) -def _clean_url_path(path, is_local_path): - # type: (str, bool) -> str +def _clean_url_path(path: str, is_local_path: bool) -> str: """ Clean the path portion of a URL. """ @@ -230,8 +220,7 @@ def _clean_url_path(path, is_local_path): return ''.join(cleaned_parts) -def _clean_link(url): - # type: (str) -> str +def _clean_link(url: str) -> str: """ Make sure a link is fully quoted. For example, if ' ' occurs in the URL, it will be replaced with "%20", @@ -247,11 +236,10 @@ def _clean_link(url): def _create_link_from_element( - anchor, # type: HTMLElement - page_url, # type: str - base_url, # type: str -): - # type: (...) -> Optional[Link] + anchor: HTMLElement, + page_url: str, + base_url: str, +) -> Optional[Link]: """ Convert an anchor element in a simple repository page to a Link. """ @@ -278,25 +266,21 @@ def _create_link_from_element( class CacheablePageContent: - def __init__(self, page): - # type: (HTMLPage) -> None + def __init__(self, page: HTMLPage) -> None: assert page.cache_link_parsing self.page = page - def __eq__(self, other): - # type: (object) -> bool + def __eq__(self, other: object) -> bool: return (isinstance(other, type(self)) and self.page.url == other.page.url) - def __hash__(self): - # type: () -> int + def __hash__(self) -> int: return hash(self.page.url) def with_cached_html_pages( - fn, # type: Callable[[HTMLPage], Iterable[Link]] -): - # type: (...) -> Callable[[HTMLPage], List[Link]] + fn: Callable[[HTMLPage], Iterable[Link]], +) -> Callable[[HTMLPage], List[Link]]: """ Given a function that parses an Iterable[Link] from an HTMLPage, cache the function's result (keyed by CacheablePageContent), unless the HTMLPage @@ -304,13 +288,11 @@ def with_cached_html_pages( """ @functools.lru_cache(maxsize=None) - def wrapper(cacheable_page): - # type: (CacheablePageContent) -> List[Link] + def wrapper(cacheable_page: CacheablePageContent) -> List[Link]: return list(fn(cacheable_page.page)) @functools.wraps(fn) - def wrapper_wrapper(page): - # type: (HTMLPage) -> List[Link] + def wrapper_wrapper(page: HTMLPage) -> List[Link]: if page.cache_link_parsing: return wrapper(CacheablePageContent(page)) return list(fn(page)) @@ -319,8 +301,7 @@ def wrapper_wrapper(page): @with_cached_html_pages -def parse_links(page): - # type: (HTMLPage) -> Iterable[Link] +def parse_links(page: HTMLPage) -> Iterable[Link]: """ Parse an HTML document, and yield its anchor elements as Link objects. """ @@ -348,12 +329,11 @@ class HTMLPage: def __init__( self, - content, # type: bytes - encoding, # type: Optional[str] - url, # type: str - cache_link_parsing=True, # type: bool - ): - # type: (...) -> None + content: bytes, + encoding: Optional[str], + url: str, + cache_link_parsing: bool = True, + ) -> None: """ :param encoding: the encoding to decode the given content. :param url: the URL from which the HTML was downloaded. @@ -366,24 +346,21 @@ def __init__( self.url = url self.cache_link_parsing = cache_link_parsing - def __str__(self): - # type: () -> str + def __str__(self) -> str: return redact_auth_from_url(self.url) def _handle_get_page_fail( - link, # type: Link - reason, # type: Union[str, Exception] - meth=None # type: Optional[Callable[..., None]] -): - # type: (...) -> None + link: Link, + reason: Union[str, Exception], + meth: Optional[Callable[..., None]] = None +) -> None: if meth is None: meth = logger.debug meth("Could not fetch URL %s: %s - skipping", link, reason) -def _make_html_page(response, cache_link_parsing=True): - # type: (Response, bool) -> HTMLPage +def _make_html_page(response: Response, cache_link_parsing: bool = True) -> HTMLPage: encoding = _get_encoding_from_headers(response.headers) return HTMLPage( response.content, @@ -392,8 +369,7 @@ def _make_html_page(response, cache_link_parsing=True): cache_link_parsing=cache_link_parsing) -def _get_html_page(link, session=None): - # type: (Link, Optional[PipSession]) -> Optional[HTMLPage] +def _get_html_page(link: Link, session: Optional[PipSession] = None) -> Optional[HTMLPage]: if session is None: raise TypeError( "_get_html_page() missing 1 required keyword argument: 'session'" @@ -465,16 +441,14 @@ class LinkCollector: def __init__( self, - session, # type: PipSession - search_scope, # type: SearchScope - ): - # type: (...) -> None + session: PipSession, + search_scope: SearchScope, + ) -> None: self.search_scope = search_scope self.session = session @classmethod - def create(cls, session, options, suppress_no_index=False): - # type: (PipSession, Values, bool) -> LinkCollector + def create(cls, session: PipSession, options: Values, suppress_no_index: bool = False) -> LinkCollector: """ :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option @@ -500,12 +474,10 @@ def create(cls, session, options, suppress_no_index=False): return link_collector @property - def find_links(self): - # type: () -> List[str] + def find_links(self) -> List[str]: return self.search_scope.find_links - def fetch_page(self, location): - # type: (Link) -> Optional[HTMLPage] + def fetch_page(self, location: Link) -> Optional[HTMLPage]: """ Fetch an HTML page containing package links. """ From 2801086913269195b6541e6b8025ca9fd058383f Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Tue, 29 Jun 2021 11:38:03 -0500 Subject: [PATCH 02/10] Create 10111.trivial.rst This is the news entry for my pull request. --- news/10111.trivial.rst | 1 + 1 file changed, 1 insertion(+) create mode 100644 news/10111.trivial.rst diff --git a/news/10111.trivial.rst b/news/10111.trivial.rst new file mode 100644 index 00000000000..e646d70f418 --- /dev/null +++ b/news/10111.trivial.rst @@ -0,0 +1 @@ +Converted type commentaries into annotations in ``pip/_internal/index``. From 71a46bc3d91a4a2ebe90fe6a0adeb7d80ae34f39 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 09:08:26 -0500 Subject: [PATCH 03/10] Update forward references/lenght of the functions Make them fit to the flake8 test. --- src/pip/_internal/index/collector.py | 18 ++++++++++++------ 1 file changed, 12 insertions(+), 6 deletions(-) diff --git a/src/pip/_internal/index/collector.py b/src/pip/_internal/index/collector.py index a0846baba83..9188094c4bf 100644 --- a/src/pip/_internal/index/collector.py +++ b/src/pip/_internal/index/collector.py @@ -266,7 +266,7 @@ def _create_link_from_element( class CacheablePageContent: - def __init__(self, page: HTMLPage) -> None: + def __init__(self, page: HTMLPage) -> None: # OK assert page.cache_link_parsing self.page = page @@ -279,8 +279,8 @@ def __hash__(self) -> int: def with_cached_html_pages( - fn: Callable[[HTMLPage], Iterable[Link]], -) -> Callable[[HTMLPage], List[Link]]: + fn: Callable[[HTMLPage], Iterable[Link]], # OK +) -> Callable[[HTMLPage], List[Link]]: # OK """ Given a function that parses an Iterable[Link] from an HTMLPage, cache the function's result (keyed by CacheablePageContent), unless the HTMLPage @@ -301,7 +301,7 @@ def wrapper_wrapper(page: HTMLPage) -> List[Link]: @with_cached_html_pages -def parse_links(page: HTMLPage) -> Iterable[Link]: +def parse_links(page: HTMLPage) -> Iterable[Link]: # OK """ Parse an HTML document, and yield its anchor elements as Link objects. """ @@ -369,7 +369,9 @@ def _make_html_page(response: Response, cache_link_parsing: bool = True) -> HTML cache_link_parsing=cache_link_parsing) -def _get_html_page(link: Link, session: Optional[PipSession] = None) -> Optional[HTMLPage]: +def _get_html_page( + link: Link, session: Optional[PipSession] = None +) -> Optional[HTMLPage]: # OK if session is None: raise TypeError( "_get_html_page() missing 1 required keyword argument: 'session'" @@ -448,7 +450,11 @@ def __init__( self.session = session @classmethod - def create(cls, session: PipSession, options: Values, suppress_no_index: bool = False) -> LinkCollector: + def create( + cls, session: PipSession, + options: Values, + suppress_no_index: bool = False + ) -> LinkCollector: # OK """ :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option From 65666b833cad13ac694f91d44feee877d24ae1dc Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 09:14:24 -0500 Subject: [PATCH 04/10] Fix forward references Convert some type annotations into strings. --- src/pip/_internal/index/collector.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/pip/_internal/index/collector.py b/src/pip/_internal/index/collector.py index 9188094c4bf..14d745eefbb 100644 --- a/src/pip/_internal/index/collector.py +++ b/src/pip/_internal/index/collector.py @@ -266,7 +266,7 @@ def _create_link_from_element( class CacheablePageContent: - def __init__(self, page: HTMLPage) -> None: # OK + def __init__(self, page: "HTMLPage") -> None: assert page.cache_link_parsing self.page = page @@ -279,8 +279,8 @@ def __hash__(self) -> int: def with_cached_html_pages( - fn: Callable[[HTMLPage], Iterable[Link]], # OK -) -> Callable[[HTMLPage], List[Link]]: # OK + fn: Callable[["HTMLPage"], Iterable[Link]], +) -> Callable[["HTMLPage"], List[Link]]: """ Given a function that parses an Iterable[Link] from an HTMLPage, cache the function's result (keyed by CacheablePageContent), unless the HTMLPage @@ -292,7 +292,7 @@ def wrapper(cacheable_page: CacheablePageContent) -> List[Link]: return list(fn(cacheable_page.page)) @functools.wraps(fn) - def wrapper_wrapper(page: HTMLPage) -> List[Link]: + def wrapper_wrapper(page: "HTMLPage") -> List[Link]: if page.cache_link_parsing: return wrapper(CacheablePageContent(page)) return list(fn(page)) @@ -301,7 +301,7 @@ def wrapper_wrapper(page: HTMLPage) -> List[Link]: @with_cached_html_pages -def parse_links(page: HTMLPage) -> Iterable[Link]: # OK +def parse_links(page: "HTMLPage") -> Iterable[Link]: """ Parse an HTML document, and yield its anchor elements as Link objects. """ @@ -371,7 +371,7 @@ def _make_html_page(response: Response, cache_link_parsing: bool = True) -> HTML def _get_html_page( link: Link, session: Optional[PipSession] = None -) -> Optional[HTMLPage]: # OK +) -> Optional["HTMLPage"]: if session is None: raise TypeError( "_get_html_page() missing 1 required keyword argument: 'session'" @@ -454,7 +454,7 @@ def create( cls, session: PipSession, options: Values, suppress_no_index: bool = False - ) -> LinkCollector: # OK + ) -> "LinkCollector": """ :param session: The Session to use to make requests. :param suppress_no_index: Whether to ignore the --no-index option From 76c011e71c9febc83c386d3123682e10a0c679f9 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 09:47:01 -0500 Subject: [PATCH 05/10] Fix the `pip/_internal/index/package_finder.py` --- src/pip/_internal/index/package_finder.py | 211 +++++++++------------- 1 file changed, 86 insertions(+), 125 deletions(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 7f2e04e7c37..352a2c8db80 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -50,11 +50,10 @@ def _check_link_requires_python( - link, # type: Link - version_info, # type: Tuple[int, int, int] - ignore_requires_python=False, # type: bool -): - # type: (...) -> bool + link: Link, + version_info: Tuple[int, int, int], + ignore_requires_python: bool = False, +) -> bool: """ Return whether the given Python version is compatible with a link's "Requires-Python" value. @@ -106,14 +105,13 @@ class LinkEvaluator: # people when reading the code. def __init__( self, - project_name, # type: str - canonical_name, # type: str - formats, # type: FrozenSet[str] - target_python, # type: TargetPython - allow_yanked, # type: bool - ignore_requires_python=None, # type: Optional[bool] - ): - # type: (...) -> None + project_name: str, + canonical_name: str, + formats: FrozenSet[str], + target_python: TargetPython, + allow_yanked: bool, + ignore_requires_python: Optional[bool] = None, + ) -> None: """ :param project_name: The user supplied package name. :param canonical_name: The canonical package name. @@ -142,8 +140,7 @@ def __init__( self.project_name = project_name - def evaluate_link(self, link): - # type: (Link) -> Tuple[bool, Optional[str]] + def evaluate_link(self, link: Link) -> Tuple[bool, Optional[str]]: """ Determine whether a link is a candidate for installation. @@ -232,11 +229,10 @@ def evaluate_link(self, link): def filter_unallowed_hashes( - candidates, # type: List[InstallationCandidate] - hashes, # type: Hashes - project_name, # type: str -): - # type: (...) -> List[InstallationCandidate] + candidates: List[InstallationCandidate], + hashes: Hashes, + project_name: str, +) -> List[InstallationCandidate]: """ Filter out candidates whose hashes aren't allowed, and return a new list of candidates. @@ -315,10 +311,9 @@ class CandidatePreferences: def __init__( self, - prefer_binary=False, # type: bool - allow_all_prereleases=False, # type: bool - ): - # type: (...) -> None + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + ) -> None: """ :param allow_all_prereleases: Whether to allow all pre-releases. """ @@ -335,11 +330,10 @@ class BestCandidateResult: def __init__( self, - candidates, # type: List[InstallationCandidate] - applicable_candidates, # type: List[InstallationCandidate] - best_candidate, # type: Optional[InstallationCandidate] - ): - # type: (...) -> None + candidates: List[InstallationCandidate], + applicable_candidates: List[InstallationCandidate], + best_candidate: Optional[InstallationCandidate], + ) -> None: """ :param candidates: A sequence of all available candidates found. :param applicable_candidates: The applicable candidates. @@ -358,14 +352,12 @@ def __init__( self.best_candidate = best_candidate - def iter_all(self): - # type: () -> Iterable[InstallationCandidate] + def iter_all(self) -> Iterable[InstallationCandidate]: """Iterate through all candidates. """ return iter(self._candidates) - def iter_applicable(self): - # type: () -> Iterable[InstallationCandidate] + def iter_applicable(self) -> Iterable[InstallationCandidate]: """Iterate through the applicable candidates. """ return iter(self._applicable_candidates) @@ -381,14 +373,13 @@ class CandidateEvaluator: @classmethod def create( cls, - project_name, # type: str - target_python=None, # type: Optional[TargetPython] - prefer_binary=False, # type: bool - allow_all_prereleases=False, # type: bool - specifier=None, # type: Optional[specifiers.BaseSpecifier] - hashes=None, # type: Optional[Hashes] - ): - # type: (...) -> CandidateEvaluator + project_name: str, + target_python: Optional[TargetPython] = None, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> CandidateEvaluator: """Create a CandidateEvaluator object. :param target_python: The target Python interpreter to use when @@ -417,14 +408,13 @@ def create( def __init__( self, - project_name, # type: str - supported_tags, # type: List[Tag] - specifier, # type: specifiers.BaseSpecifier - prefer_binary=False, # type: bool - allow_all_prereleases=False, # type: bool - hashes=None, # type: Optional[Hashes] - ): - # type: (...) -> None + project_name: str, + supported_tags: List[tag], + specifier: specifiers.BaseSpecifier, + prefer_binary: bool = False, + allow_all_prereleases: bool = False, + hashes: Optional[Hashes] = None, + ) -> None: """ :param supported_tags: The PEP 425 tags supported by the target Python in order of preference (most preferred first). @@ -444,9 +434,8 @@ def __init__( def get_applicable_candidates( self, - candidates, # type: List[InstallationCandidate] - ): - # type: (...) -> List[InstallationCandidate] + candidates: List[InstallationCandidate], + ) -> List[InstallationCandidate]: """ Return the applicable candidates from a list of candidates. """ @@ -480,8 +469,7 @@ def get_applicable_candidates( return sorted(filtered_applicable_candidates, key=self._sort_key) - def _sort_key(self, candidate): - # type: (InstallationCandidate) -> CandidateSortingKey + def _sort_key(self, candidate: InstallationCandidate) -> CandidateSortingKey: """ Function to pass as the `key` argument to a call to sorted() to sort InstallationCandidates by preference. @@ -545,9 +533,8 @@ def _sort_key(self, candidate): def sort_best_candidate( self, - candidates, # type: List[InstallationCandidate] - ): - # type: (...) -> Optional[InstallationCandidate] + candidates: List[InstallationCandidate], + ) -> Optional[InstallationCandidate]: """ Return the best candidate per the instance's sort order, or None if no candidate is acceptable. @@ -559,9 +546,8 @@ def sort_best_candidate( def compute_best_candidate( self, - candidates, # type: List[InstallationCandidate] - ): - # type: (...) -> BestCandidateResult + candidates: List[InstallationCandidate], + ) -> BestCandidateResult: """ Compute and return a `BestCandidateResult` instance. """ @@ -585,14 +571,13 @@ class PackageFinder: def __init__( self, - link_collector, # type: LinkCollector - target_python, # type: TargetPython - allow_yanked, # type: bool - format_control=None, # type: Optional[FormatControl] - candidate_prefs=None, # type: CandidatePreferences - ignore_requires_python=None, # type: Optional[bool] - ): - # type: (...) -> None + link_collector: LinkCollector, + target_python: TargetPython, + allow_yanked: bool, + format_control: Optional[FormatControl] = None, + candidate_prefs: Optional[CandidatePreferences] = None, + ignore_requires_python: Optional[bool] = None, + ) -> None: """ This constructor is primarily meant to be used by the create() class method and from tests. @@ -626,11 +611,10 @@ def __init__( @classmethod def create( cls, - link_collector, # type: LinkCollector - selection_prefs, # type: SelectionPreferences - target_python=None, # type: Optional[TargetPython] - ): - # type: (...) -> PackageFinder + link_collector: LinkCollector, + selection_prefs: SelectionPreferences, + target_python: Optional[TargetPython] = None, + ) -> PackageFinder: """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a @@ -657,56 +641,45 @@ def create( ) @property - def target_python(self): - # type: () -> TargetPython + def target_python(self) -> TargetPython: return self._target_python @property - def search_scope(self): - # type: () -> SearchScope + def search_scope(self) -> SearchScope: return self._link_collector.search_scope @search_scope.setter - def search_scope(self, search_scope): - # type: (SearchScope) -> None + def search_scope(self, search_scope: SearchScope) -> None: self._link_collector.search_scope = search_scope @property - def find_links(self): - # type: () -> List[str] + def find_links(self) -> List[str]: return self._link_collector.find_links @property - def index_urls(self): - # type: () -> List[str] + def index_urls(self) -> List[str]: return self.search_scope.index_urls @property - def trusted_hosts(self): - # type: () -> Iterable[str] + def trusted_hosts(self) -> Iterable[str]: for host_port in self._link_collector.session.pip_trusted_origins: yield build_netloc(*host_port) @property - def allow_all_prereleases(self): - # type: () -> bool + def allow_all_prereleases(self) -> bool: return self._candidate_prefs.allow_all_prereleases - def set_allow_all_prereleases(self): - # type: () -> None + def set_allow_all_prereleases(self) -> None: self._candidate_prefs.allow_all_prereleases = True @property - def prefer_binary(self): - # type: () -> bool + def prefer_binary(self) -> bool: return self._candidate_prefs.prefer_binary - def set_prefer_binary(self): - # type: () -> None + def set_prefer_binary(self) -> None: self._candidate_prefs.prefer_binary = True - def make_link_evaluator(self, project_name): - # type: (str) -> LinkEvaluator + def make_link_evaluator(self, project_name: str) -> LinkEvaluator: canonical_name = canonicalize_name(project_name) formats = self.format_control.get_allowed_formats(canonical_name) @@ -719,8 +692,7 @@ def make_link_evaluator(self, project_name): ignore_requires_python=self._ignore_requires_python, ) - def _sort_links(self, links): - # type: (Iterable[Link]) -> List[Link] + def _sort_links(self, links: Iterable[Link]) -> List[Link]: """ Returns elements of links in order, non-egg links first, egg links second, while eliminating duplicates @@ -736,16 +708,14 @@ def _sort_links(self, links): no_eggs.append(link) return no_eggs + eggs - def _log_skipped_link(self, link, reason): - # type: (Link, str) -> None + def _log_skipped_link(self, link: Link, reason: str) -> None: if link not in self._logged_links: # Put the link at the end so the reason is more visible and because # the link string is usually very long. logger.debug('Skipping link: %s: %s', reason, link) self._logged_links.add(link) - def get_install_candidate(self, link_evaluator, link): - # type: (LinkEvaluator, Link) -> Optional[InstallationCandidate] + def get_install_candidate(self, link_evaluator: LinkEvaluator, link: Link) -> Optional[InstallationCandidate]: """ If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. @@ -762,8 +732,7 @@ def get_install_candidate(self, link_evaluator, link): version=result, ) - def evaluate_links(self, link_evaluator, links): - # type: (LinkEvaluator, Iterable[Link]) -> List[InstallationCandidate] + def evaluate_links(self, link_evaluator: LinkEvaluator, links: Iterable[Link]) -> List[InstallationCandidate]: """ Convert links that are candidates to InstallationCandidate objects. """ @@ -775,8 +744,7 @@ def evaluate_links(self, link_evaluator, links): return candidates - def process_project_url(self, project_url, link_evaluator): - # type: (Link, LinkEvaluator) -> List[InstallationCandidate] + def process_project_url(self, project_url: Link, link_evaluator: LinkEvaluator) -> List[InstallationCandidate]: logger.debug( 'Fetching project page and analyzing links: %s', project_url, ) @@ -795,8 +763,7 @@ def process_project_url(self, project_url, link_evaluator): return package_links @functools.lru_cache(maxsize=None) - def find_all_candidates(self, project_name): - # type: (str) -> List[InstallationCandidate] + def find_all_candidates(self, project_name: str) -> List[InstallationCandidate]: """Find all available InstallationCandidate for project_name This checks index_urls and find_links. @@ -843,11 +810,10 @@ def find_all_candidates(self, project_name): def make_candidate_evaluator( self, - project_name, # type: str - specifier=None, # type: Optional[specifiers.BaseSpecifier] - hashes=None, # type: Optional[Hashes] - ): - # type: (...) -> CandidateEvaluator + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> CandidateEvaluator: """Create a CandidateEvaluator object to use. """ candidate_prefs = self._candidate_prefs @@ -863,11 +829,10 @@ def make_candidate_evaluator( @functools.lru_cache(maxsize=None) def find_best_candidate( self, - project_name, # type: str - specifier=None, # type: Optional[specifiers.BaseSpecifier] - hashes=None, # type: Optional[Hashes] - ): - # type: (...) -> BestCandidateResult + project_name: str, + specifier: Optional[specifiers.BaseSpecifier] = None, + hashes: Optional[Hashes] = None, + ) -> BestCandidateResult: """Find matches for the given project and specifier. :param specifier: An optional object implementing `filter` @@ -884,8 +849,7 @@ def find_best_candidate( ) return candidate_evaluator.compute_best_candidate(candidates) - def find_requirement(self, req, upgrade): - # type: (InstallRequirement, bool) -> Optional[InstallationCandidate] + def find_requirement(self, req: InstallRequirement, upgrade: bool) -> Optional[InstallationCandidate]: """Try to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean @@ -902,8 +866,7 @@ def find_requirement(self, req, upgrade): if req.satisfied_by is not None: installed_version = parse_version(req.satisfied_by.version) - def _format_versions(cand_iter): - # type: (Iterable[InstallationCandidate]) -> str + def _format_versions(cand_iter: -> Iterable[InstallationCandidate]) -> str: # This repeated parse_version and str() conversion is needed to # handle different vendoring sources from pip and pkg_resources. # If we stop using the pkg_resources provided specifier and start @@ -966,8 +929,7 @@ def _format_versions(cand_iter): return best_candidate -def _find_name_version_sep(fragment, canonical_name): - # type: (str, str) -> int +def _find_name_version_sep(fragment: str, canonical_name: str) -> int: """Find the separator's index based on the package's canonical name. :param fragment: A + filename "fragment" (stem) or @@ -993,8 +955,7 @@ def _find_name_version_sep(fragment, canonical_name): raise ValueError(f"{fragment} does not match {canonical_name}") -def _extract_version_from_fragment(fragment, canonical_name): - # type: (str, str) -> Optional[str] +def _extract_version_from_fragment(fragment: str, canonical_name: str) -> Optional[str]: """Parse the version string from a + filename "fragment" (stem) or egg fragment. From f6282daf24eef7e5dd5401d6a2c2cc5df500ccba Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 09:50:12 -0500 Subject: [PATCH 06/10] Fix an annotation mistake I annotated an argument wrong. --- src/pip/_internal/index/package_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 352a2c8db80..02e983617c5 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -866,7 +866,7 @@ def find_requirement(self, req: InstallRequirement, upgrade: bool) -> Optional[I if req.satisfied_by is not None: installed_version = parse_version(req.satisfied_by.version) - def _format_versions(cand_iter: -> Iterable[InstallationCandidate]) -> str: + def _format_versions(cand_iter: Iterable[InstallationCandidate]) -> str: # This repeated parse_version and str() conversion is needed to # handle different vendoring sources from pip and pkg_resources. # If we stop using the pkg_resources provided specifier and start From f28add32ad0956d27bb4810402297041ba0bc97c Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 09:55:00 -0500 Subject: [PATCH 07/10] Fix a forward reference Seems like "tag" is not defined, so I just annotated as a string. --- src/pip/_internal/index/package_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 02e983617c5..3d0b1a46d2f 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -409,7 +409,7 @@ def create( def __init__( self, project_name: str, - supported_tags: List[tag], + supported_tags: List["tag"], specifier: specifiers.BaseSpecifier, prefer_binary: bool = False, allow_all_prereleases: bool = False, From 5ce25b90fdd28182b58bfe3d3da9945c164b6a6d Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 11:52:56 -0500 Subject: [PATCH 08/10] Fix an annotation mistake Maybe "tag" was originally "Tag". I fixed that simple mistake. --- src/pip/_internal/index/package_finder.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 3d0b1a46d2f..45f0190aadd 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -409,7 +409,7 @@ def create( def __init__( self, project_name: str, - supported_tags: List["tag"], + supported_tags: List[Tag], specifier: specifiers.BaseSpecifier, prefer_binary: bool = False, allow_all_prereleases: bool = False, From 663ee8f97926867221218fe6274c594f8a4a2c63 Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 11:58:01 -0500 Subject: [PATCH 09/10] Fix forward references and line lenght These changes were suggested by the flake8 test. --- src/pip/_internal/index/package_finder.py | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 45f0190aadd..2be92c416ed 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -379,7 +379,7 @@ def create( allow_all_prereleases: bool = False, specifier: Optional[specifiers.BaseSpecifier] = None, hashes: Optional[Hashes] = None, - ) -> CandidateEvaluator: + ) -> "CandidateEvaluator": """Create a CandidateEvaluator object. :param target_python: The target Python interpreter to use when @@ -614,7 +614,7 @@ def create( link_collector: LinkCollector, selection_prefs: SelectionPreferences, target_python: Optional[TargetPython] = None, - ) -> PackageFinder: + ) -> "PackageFinder": """Create a PackageFinder. :param selection_prefs: The candidate selection preferences, as a @@ -715,7 +715,9 @@ def _log_skipped_link(self, link: Link, reason: str) -> None: logger.debug('Skipping link: %s: %s', reason, link) self._logged_links.add(link) - def get_install_candidate(self, link_evaluator: LinkEvaluator, link: Link) -> Optional[InstallationCandidate]: + def get_install_candidate( + self, link_evaluator: LinkEvaluator, link: Link + ) -> Optional[InstallationCandidate]: """ If the link is a candidate for install, convert it to an InstallationCandidate and return it. Otherwise, return None. @@ -732,7 +734,9 @@ def get_install_candidate(self, link_evaluator: LinkEvaluator, link: Link) -> Op version=result, ) - def evaluate_links(self, link_evaluator: LinkEvaluator, links: Iterable[Link]) -> List[InstallationCandidate]: + def evaluate_links( + self, link_evaluator: LinkEvaluator, links: Iterable[Link] + ) -> List[InstallationCandidate]: """ Convert links that are candidates to InstallationCandidate objects. """ From c84fd81159eb91c4500d4ea8b41c9d5e5932cace Mon Sep 17 00:00:00 2001 From: Diego Ramirez Date: Mon, 5 Jul 2021 12:01:32 -0500 Subject: [PATCH 10/10] Fix the annotations lenght flake8 told me they were too long. --- src/pip/_internal/index/package_finder.py | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/pip/_internal/index/package_finder.py b/src/pip/_internal/index/package_finder.py index 2be92c416ed..49c2bff4c53 100644 --- a/src/pip/_internal/index/package_finder.py +++ b/src/pip/_internal/index/package_finder.py @@ -748,7 +748,9 @@ def evaluate_links( return candidates - def process_project_url(self, project_url: Link, link_evaluator: LinkEvaluator) -> List[InstallationCandidate]: + def process_project_url( + self, project_url: Link, link_evaluator: LinkEvaluator + ) -> List[InstallationCandidate]: logger.debug( 'Fetching project page and analyzing links: %s', project_url, ) @@ -853,7 +855,9 @@ def find_best_candidate( ) return candidate_evaluator.compute_best_candidate(candidates) - def find_requirement(self, req: InstallRequirement, upgrade: bool) -> Optional[InstallationCandidate]: + def find_requirement( + self, req: InstallRequirement, upgrade: bool + ) -> Optional[InstallationCandidate]: """Try to find a Link matching req Expects req, an InstallRequirement and upgrade, a boolean