Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Complete type hinting of piptools.repositories package #1341

Merged
merged 4 commits into from
Mar 8, 2021
Merged
Show file tree
Hide file tree
Changes from 1 commit
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Jump to
Jump to file
Failed to load files.
Diff view
Diff view
4 changes: 2 additions & 2 deletions piptools/_compat/contextlib.py
Original file line number Diff line number Diff line change
Expand Up @@ -16,10 +16,10 @@ class nullcontext:
TODO: replace with `contextlib.nullcontext()` after Python 3.6 being dropped
"""

def __init__(self, enter_result: Optional[_T] = None) -> None:
def __init__(self, enter_result: _T) -> None:
self.enter_result = enter_result

def __enter__(self) -> Optional[_T]:
def __enter__(self) -> _T:
return self.enter_result

def __exit__(
Expand Down
4 changes: 2 additions & 2 deletions piptools/cache.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
from pip._vendor.packaging.requirements import Requirement

from .exceptions import PipToolsError
from .utils import as_tuple, key_from_req, lookup_table
from .utils import as_tuple, key_from_req, lookup_table_from_tuples

CacheKey = Tuple[str, str]
CacheLookup = Dict[str, List[str]]
Expand Down Expand Up @@ -166,7 +166,7 @@ def _reverse_dependencies(
"""
# First, collect all the dependencies into a sequence of (parent, child)
# tuples, like [('flake8', 'pep8'), ('flake8', 'mccabe'), ...]
return lookup_table(
return lookup_table_from_tuples(
(key_from_req(Requirement(dep_name)), name)
for name, version_and_extras in cache_keys
for dep_name in self.cache[name][version_and_extras]
Expand Down
51 changes: 35 additions & 16 deletions piptools/repositories/local.py
Original file line number Diff line number Diff line change
@@ -1,21 +1,31 @@
import optparse
from contextlib import contextmanager
from typing import Dict, Iterator, List, Optional, Set, cast

from pip._internal.index.package_finder import PackageFinder
from pip._internal.models.candidate import InstallationCandidate
from pip._internal.req import InstallRequirement
from pip._internal.utils.hashes import FAVORITE_HASH
from pip._vendor.requests import Session

from piptools.utils import as_tuple, key_from_ireq, make_install_requirement

from .base import BaseRepository
from .pypi import PyPIRepository


def ireq_satisfied_by_existing_pin(ireq, existing_pin):
def ireq_satisfied_by_existing_pin(
ireq: InstallRequirement, existing_pin: InstallationCandidate
) -> bool:
"""
Return True if the given InstallationRequirement is satisfied by the
previously encountered version pin.
"""
version = next(iter(existing_pin.req.specifier)).version
return ireq.req.specifier.contains(
result = ireq.req.specifier.contains(
version, prereleases=existing_pin.req.specifier.prereleases
)
return cast(bool, result)


class LocalRequirementsRepository(BaseRepository):
Expand All @@ -29,36 +39,43 @@ class LocalRequirementsRepository(BaseRepository):
PyPI. This keeps updates to the requirements.txt down to a minimum.
"""

def __init__(self, existing_pins, proxied_repository, reuse_hashes=True):
def __init__(
self,
existing_pins: Dict[str, InstallationCandidate],
proxied_repository: PyPIRepository,
reuse_hashes: bool = True,
):
self._reuse_hashes = reuse_hashes
self.repository = proxied_repository
self.existing_pins = existing_pins

@property
def options(self):
return self.repository.options
def options(self) -> List[optparse.Option]:
return cast(List[optparse.Option], self.repository.options)

@property
def finder(self):
def finder(self) -> PackageFinder:
return self.repository.finder

@property
def session(self):
def session(self) -> Session:
return self.repository.session

@property
def DEFAULT_INDEX_URL(self):
return self.repository.DEFAULT_INDEX_URL
def DEFAULT_INDEX_URL(self) -> str:
return cast(str, self.repository.DEFAULT_INDEX_URL)

def clear_caches(self):
def clear_caches(self) -> None:
self.repository.clear_caches()

@contextmanager
def freshen_build_caches(self):
def freshen_build_caches(self) -> Iterator[None]:
with self.repository.freshen_build_caches():
yield

def find_best_match(self, ireq, prereleases=None):
def find_best_match(
self, ireq: InstallRequirement, prereleases: Optional[bool] = None
) -> InstallationCandidate:
key = key_from_ireq(ireq)
existing_pin = self.existing_pins.get(key)
if existing_pin and ireq_satisfied_by_existing_pin(ireq, existing_pin):
Expand All @@ -67,10 +84,10 @@ def find_best_match(self, ireq, prereleases=None):
else:
return self.repository.find_best_match(ireq, prereleases)

def get_dependencies(self, ireq):
def get_dependencies(self, ireq: InstallRequirement) -> Set[InstallRequirement]:
return self.repository.get_dependencies(ireq)

def get_hashes(self, ireq):
def get_hashes(self, ireq: InstallRequirement) -> Set[str]:
existing_pin = self._reuse_hashes and self.existing_pins.get(
key_from_ireq(ireq)
)
Expand All @@ -84,9 +101,11 @@ def get_hashes(self, ireq):
return self.repository.get_hashes(ireq)

@contextmanager
def allow_all_wheels(self):
def allow_all_wheels(self) -> Iterator[None]:
with self.repository.allow_all_wheels():
yield

def copy_ireq_dependencies(self, source, dest):
def copy_ireq_dependencies(
self, source: InstallRequirement, dest: InstallRequirement
) -> None:
self.repository.copy_ireq_dependencies(source, dest)