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

Add type annotations for pip._internal.download, pip._internal.wheel and pip._internal.pep425tags #6067

Merged
merged 10 commits into from
Dec 16, 2018
70 changes: 60 additions & 10 deletions src/pip/_internal/download.py
Original file line number Diff line number Diff line change
Expand Up @@ -48,7 +48,13 @@
from pip._internal.vcs import vcs

if MYPY_CHECK_RUNNING:
from typing import Optional # noqa: F401
from typing import ( # noqa: F401
Optional, Tuple, Dict, IO, Text, Union
)
from pip._internal.models.link import Link # noqa: F401
from pip._internal.utils.hashes import Hashes # noqa: F401
# cannot import alias directly here, fixed in mypy==0.641
import pip._internal.vcs as vcs_type_aliases # noqa: F401

try:
import ssl # noqa
Expand Down Expand Up @@ -139,8 +145,9 @@ def user_agent():
class MultiDomainBasicAuth(AuthBase):

def __init__(self, prompting=True):
# type: (bool) -> None
self.prompting = prompting
self.passwords = {}
self.passwords = {} # type: Dict[str, vcs_type_aliases.AuthInfo]

def __call__(self, req):
parsed = urllib_parse.urlparse(req.url)
Expand Down Expand Up @@ -398,6 +405,7 @@ def request(self, method, url, *args, **kwargs):


def get_file_content(url, comes_from=None, session=None):
# type: (str, Optional[str], Optional[PipSession]) -> Tuple[str, Text]
"""Gets the content of a file; it may be a filename, file: URL, or
http: URL. Returns (location, content). Content is unicode.

Expand Down Expand Up @@ -448,6 +456,7 @@ def get_file_content(url, comes_from=None, session=None):


def is_url(name):
# type: (Union[str, Text]) -> bool
"""Returns true if the name looks like a URL"""
if ':' not in name:
return False
Expand All @@ -456,6 +465,7 @@ def is_url(name):


def url_to_path(url):
# type: (str) -> str
"""
Convert a file: URL to a path.
"""
Expand All @@ -473,6 +483,7 @@ def url_to_path(url):


def path_to_url(path):
# type: (Union[str, Text]) -> str
"""
Convert a path to a file: URL. The path will be made absolute and have
quoted path parts.
Expand All @@ -483,6 +494,7 @@ def path_to_url(path):


def is_archive_file(name):
# type: (str) -> bool
"""Return True if `name` is a considered as an archive file."""
ext = splitext(name)[1].lower()
if ext in ARCHIVE_EXTENSIONS:
Expand All @@ -503,14 +515,17 @@ def _get_used_vcs_backend(link):


def is_vcs_url(link):
# type: (Link) -> bool
return bool(_get_used_vcs_backend(link))


def is_file_url(link):
# type: (Link) -> bool
return link.url.lower().startswith('file:')


def is_dir_url(link):
# type: (Link) -> bool
"""Return whether a file:// Link points to a directory.

``link`` must not have any other scheme but file://. Call is_file_url()
Expand All @@ -525,7 +540,14 @@ def _progress_indicator(iterable, *args, **kwargs):
return iterable


def _download_url(resp, link, content_file, hashes, progress_bar):
def _download_url(
resp, # type: Response
link, # type: Link
content_file, # type: IO
hashes, # type: Hashes
progress_bar # type: str
):
# type: (...) -> None
try:
total_length = int(resp.headers['content-length'])
except (ValueError, KeyError, TypeError):
Expand Down Expand Up @@ -647,8 +669,15 @@ def _copy_file(filename, location, link):
logger.info('Saved %s', display_path(download_location))


def unpack_http_url(link, location, download_dir=None,
session=None, hashes=None, progress_bar="on"):
def unpack_http_url(
link, # type: Link
location, # type: str
download_dir=None, # type: Optional[str]
session=None, # type: Optional[PipSession]
hashes=None, # type: Optional[Hashes]
progress_bar="on" # type: str
):
# type: (...) -> None
if session is None:
raise TypeError(
"unpack_http_url() missing 1 required keyword argument: 'session'"
Expand Down Expand Up @@ -685,7 +714,13 @@ def unpack_http_url(link, location, download_dir=None,
os.unlink(from_path)


def unpack_file_url(link, location, download_dir=None, hashes=None):
def unpack_file_url(
link, # type: Link
location, # type: str
download_dir=None, # type: Optional[str]
hashes=None # type: Optional[Hashes]
):
# type: (...) -> None
"""Unpack link into location.

If download_dir is provided and link points to a file, make a copy
Expand Down Expand Up @@ -798,9 +833,16 @@ def request(self, host, handler, request_body, verbose=False):
raise


def unpack_url(link, location, download_dir=None,
only_download=False, session=None, hashes=None,
progress_bar="on"):
def unpack_url(
link, # type: Optional[Link]
location, # type: Optional[str]
download_dir=None, # type: Optional[str]
only_download=False, # type: bool
session=None, # type: Optional[PipSession]
hashes=None, # type: Optional[Hashes]
progress_bar="on" # type: str
):
# type: (...) -> None
"""Unpack link.
If link is a VCS link:
if only_download, export into download_dir and ignore location
Expand Down Expand Up @@ -840,7 +882,14 @@ def unpack_url(link, location, download_dir=None,
write_delete_marker_file(location)


def _download_http_url(link, session, temp_dir, hashes, progress_bar):
def _download_http_url(
link, # type: Link
session, # type: PipSession
temp_dir, # type: str
hashes, # type: Hashes
progress_bar # type: str
):
# type: (...) -> Tuple[str, str]
"""Download link url into temp_dir using provided session"""
target_url = link.url.split('#', 1)[0]
try:
Expand Down Expand Up @@ -900,6 +949,7 @@ def _download_http_url(link, session, temp_dir, hashes, progress_bar):


def _check_download_dir(link, download_dir, hashes):
# type: (Link, str, Hashes) -> Optional[str]
""" Check download_dir for previously downloaded file with correct hash
If a correct file is found return its path else None
"""
Expand Down
57 changes: 46 additions & 11 deletions src/pip/_internal/pep425tags.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,22 @@

import pip._internal.utils.glibc
from pip._internal.utils.compat import get_extension_suffixes
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

if MYPY_CHECK_RUNNING:
from typing import ( # noqa: F401
Tuple, Callable, List, Optional, Union, Dict
)

Pep425Tag = Tuple[str, str, str]

logger = logging.getLogger(__name__)

_osx_arch_pat = re.compile(r'(.+)_(\d+)_(\d+)_(.+)')


def get_config_var(var):
# type: (str) -> Optional[str]
try:
return sysconfig.get_config_var(var)
except IOError as e: # Issue #1074
Expand All @@ -27,6 +36,7 @@ def get_config_var(var):


def get_abbr_impl():
# type: () -> str
"""Return abbreviated implementation name."""
if hasattr(sys, 'pypy_version_info'):
pyimpl = 'pp'
Expand All @@ -40,6 +50,7 @@ def get_abbr_impl():


def get_impl_ver():
# type: () -> str
"""Return implementation version."""
impl_ver = get_config_var("py_version_nodot")
if not impl_ver or get_abbr_impl() == 'pp':
Expand All @@ -48,24 +59,29 @@ def get_impl_ver():


def get_impl_version_info():
# type: () -> Tuple[int, ...]
"""Return sys.version_info-like tuple for use in decrementing the minor
version."""
if get_abbr_impl() == 'pp':
# as per https://github.com/pypa/pip/issues/2882
return (sys.version_info[0], sys.pypy_version_info.major,
sys.pypy_version_info.minor)
# attrs exist only on pypy
return (sys.version_info[0],
sys.pypy_version_info.major, # type: ignore
sys.pypy_version_info.minor) # type: ignore
else:
return sys.version_info[0], sys.version_info[1]


def get_impl_tag():
# type: () -> str
"""
Returns the Tag for this specific implementation.
"""
return "{}{}".format(get_abbr_impl(), get_impl_ver())


def get_flag(var, fallback, expected=True, warn=True):
# type: (str, Callable[..., bool], Union[bool, int], bool) -> bool
"""Use a fallback method for determining SOABI flags if the needed config
var is unset or unavailable."""
val = get_config_var(var)
Expand All @@ -78,6 +94,7 @@ def get_flag(var, fallback, expected=True, warn=True):


def get_abi_tag():
# type: () -> Optional[str]
"""Return the ABI tag based on SOABI (if available) or emulate SOABI
(CPython 2, PyPy)."""
soabi = get_config_var('SOABI')
Expand Down Expand Up @@ -112,10 +129,12 @@ def get_abi_tag():


def _is_running_32bit():
# type: () -> bool
return sys.maxsize == 2147483647


def get_platform():
# type: () -> str
"""Return our platform name 'win32', 'linux_x86_64'"""
if sys.platform == 'darwin':
# distutils.util.get_platform() returns the release based on the value
Expand All @@ -142,6 +161,7 @@ def get_platform():


def is_manylinux1_compatible():
# type: () -> bool
# Only Linux, and only x86-64 / i686
if get_platform() not in {"linux_x86_64", "linux_i686"}:
return False
Expand All @@ -159,6 +179,7 @@ def is_manylinux1_compatible():


def is_manylinux2010_compatible():
# type: () -> bool
# Only Linux, and only x86-64 / i686
if get_platform() not in {"linux_x86_64", "linux_i686"}:
return False
Expand All @@ -176,12 +197,14 @@ def is_manylinux2010_compatible():


def get_darwin_arches(major, minor, machine):
# type: (int, int, str) -> List[str]
"""Return a list of supported arches (including group arches) for
the given major, minor and machine architecture of an macOS machine.
"""
arches = []

def _supports_arch(major, minor, arch):
# type: (int, int, str) -> bool
# Looking at the application support for macOS versions in the chart
# provided by https://en.wikipedia.org/wiki/OS_X#Versions it appears
# our timeline looks roughly like:
Expand Down Expand Up @@ -222,7 +245,7 @@ def _supports_arch(major, minor, arch):
("intel", ("x86_64", "i386")),
("fat64", ("x86_64", "ppc64")),
("fat32", ("x86_64", "i386", "ppc")),
])
]) # type: Dict[str, Tuple[str, ...]]

if _supports_arch(major, minor, machine):
arches.append(machine)
Expand All @@ -236,8 +259,24 @@ def _supports_arch(major, minor, arch):
return arches


def get_supported(versions=None, noarch=False, platform=None,
impl=None, abi=None):
def get_all_minor_versions_as_strings(version_info):
# type: (Tuple[int, ...]) -> List[str]
versions = []
major = version_info[:-1]
# Support all previous minor Python versions.
for minor in range(version_info[-1], -1, -1):
versions.append(''.join(map(str, major + (minor,))))
return versions


def get_supported(
versions=None, # type: Optional[List[str]]
noarch=False, # type: bool
platform=None, # type: Optional[str]
impl=None, # type: Optional[str]
abi=None # type: Optional[str]
):
# type: (...) -> List[Pep425Tag]
"""Return a list of supported tags for each version specified in
`versions`.

Expand All @@ -254,16 +293,12 @@ def get_supported(versions=None, noarch=False, platform=None,

# Versions must be given with respect to the preference
if versions is None:
versions = []
version_info = get_impl_version_info()
major = version_info[:-1]
# Support all previous minor Python versions.
for minor in range(version_info[-1], -1, -1):
versions.append(''.join(map(str, major + (minor,))))
versions = get_all_minor_versions_as_strings(version_info)

impl = impl or get_abbr_impl()

abis = []
abis = [] # type: List[str]

abi = abi or get_abi_tag()
if abi:
Expand Down
Loading