Skip to content

Commit

Permalink
Add type annotations for pip._internal.download, pip._internal.wheel …
Browse files Browse the repository at this point in the history
…and pip._internal.pep425tags (#6067)

References #4748, #6038.
  • Loading branch information
mkurnikov authored and pradyunsg committed Dec 16, 2018
1 parent 5d2d16e commit 7696e7e
Show file tree
Hide file tree
Showing 3 changed files with 195 additions and 50 deletions.
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

0 comments on commit 7696e7e

Please sign in to comment.