未验证 提交 69a4cb3e 编写于 作者: S Stéphane Bidoul 提交者: GitHub

Merge pull request #8296 from deveshks/mypy-pip-internal

Complete type annotations in "pip._internal.{build_env,self_outdated_check,exceptions}"
"""Build Environment used for isolation during sdist building
"""
# The following comment should be removed at some point in the future.
# mypy: strict-optional=False
# mypy: disallow-untyped-defs=False
import logging
import os
import sys
......@@ -22,7 +18,8 @@ from pip._internal.utils.temp_dir import TempDirectory, tempdir_kinds
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
from typing import Tuple, Set, Iterable, Optional, List
from types import TracebackType
from typing import Tuple, Set, Iterable, Optional, List, Type
from pip._internal.index.package_finder import PackageFinder
logger = logging.getLogger(__name__)
......@@ -110,6 +107,7 @@ class BuildEnvironment(object):
).format(system_sites=system_sites, lib_dirs=self._lib_dirs))
def __enter__(self):
# type: () -> None
self._save_env = {
name: os.environ.get(name, None)
for name in ('PATH', 'PYTHONNOUSERSITE', 'PYTHONPATH')
......@@ -128,7 +126,13 @@ class BuildEnvironment(object):
'PYTHONPATH': os.pathsep.join(pythonpath),
})
def __exit__(self, exc_type, exc_val, exc_tb):
def __exit__(
self,
exc_type, # type: Optional[Type[BaseException]]
exc_val, # type: Optional[BaseException]
exc_tb # type: Optional[TracebackType]
):
# type: (...) -> None
for varname, old_value in self._save_env.items():
if old_value is None:
os.environ.pop(varname, None)
......@@ -159,7 +163,7 @@ class BuildEnvironment(object):
finder, # type: PackageFinder
requirements, # type: Iterable[str]
prefix_as_string, # type: str
message # type: Optional[str]
message # type: str
):
# type: (...) -> None
prefix = self._prefixes[prefix_as_string]
......@@ -206,16 +210,32 @@ class NoOpBuildEnvironment(BuildEnvironment):
"""
def __init__(self):
# type: () -> None
pass
def __enter__(self):
# type: () -> None
pass
def __exit__(self, exc_type, exc_val, exc_tb):
def __exit__(
self,
exc_type, # type: Optional[Type[BaseException]]
exc_val, # type: Optional[BaseException]
exc_tb # type: Optional[TracebackType]
):
# type: (...) -> None
pass
def cleanup(self):
# type: () -> None
pass
def install_requirements(self, finder, requirements, prefix, message):
def install_requirements(
self,
finder, # type: PackageFinder
requirements, # type: Iterable[str]
prefix_as_string, # type: str
message # type: str
):
# type: (...) -> None
raise NotImplementedError()
"""Exceptions used throughout package"""
# The following comment should be removed at some point in the future.
# mypy: disallow-untyped-defs=False
from __future__ import absolute_import
from itertools import chain, groupby, repeat
......@@ -12,9 +9,15 @@ from pip._vendor.six import iteritems
from pip._internal.utils.typing import MYPY_CHECK_RUNNING
if MYPY_CHECK_RUNNING:
from typing import Optional
from typing import Optional, List, Dict
from pip._vendor.pkg_resources import Distribution
from pip._vendor.six.moves import configparser
from pip._internal.req.req_install import InstallRequirement
from pip._vendor.six import PY3
if PY3:
from hashlib import _Hash
else:
from hashlib import _hash as _Hash
class PipError(Exception):
......@@ -105,12 +108,15 @@ class HashErrors(InstallationError):
"""Multiple HashError instances rolled into one for reporting"""
def __init__(self):
self.errors = []
# type: () -> None
self.errors = [] # type: List[HashError]
def append(self, error):
# type: (HashError) -> None
self.errors.append(error)
def __str__(self):
# type: () -> str
lines = []
self.errors.sort(key=lambda e: e.order)
for cls, errors_of_cls in groupby(self.errors, lambda e: e.__class__):
......@@ -118,11 +124,14 @@ class HashErrors(InstallationError):
lines.extend(e.body() for e in errors_of_cls)
if lines:
return '\n'.join(lines)
return ''
def __nonzero__(self):
# type: () -> bool
return bool(self.errors)
def __bool__(self):
# type: () -> bool
return self.__nonzero__()
......@@ -144,8 +153,10 @@ class HashError(InstallationError):
"""
req = None # type: Optional[InstallRequirement]
head = ''
order = None # type: Optional[int]
def body(self):
# type: () -> str
"""Return a summary of me for display under the heading.
This default implementation simply prints a description of the
......@@ -158,9 +169,11 @@ class HashError(InstallationError):
return ' {}'.format(self._requirement_name())
def __str__(self):
# type: () -> str
return '{}\n{}'.format(self.head, self.body())
def _requirement_name(self):
# type: () -> str
"""Return a description of the requirement that triggered me.
This default implementation returns long description of the req, with
......@@ -201,6 +214,7 @@ class HashMissing(HashError):
'has a hash.)')
def __init__(self, gotten_hash):
# type: (str) -> None
"""
:param gotten_hash: The hash of the (possibly malicious) archive we
just downloaded
......@@ -208,6 +222,7 @@ class HashMissing(HashError):
self.gotten_hash = gotten_hash
def body(self):
# type: () -> str
# Dodge circular import.
from pip._internal.utils.hashes import FAVORITE_HASH
......@@ -250,6 +265,7 @@ class HashMismatch(HashError):
'someone may have tampered with them.')
def __init__(self, allowed, gots):
# type: (Dict[str, List[str]], Dict[str, _Hash]) -> None
"""
:param allowed: A dict of algorithm names pointing to lists of allowed
hex digests
......@@ -260,10 +276,12 @@ class HashMismatch(HashError):
self.gots = gots
def body(self):
# type: () -> str
return ' {}:\n{}'.format(self._requirement_name(),
self._hash_comparison())
def _hash_comparison(self):
# type: () -> str
"""
Return a comparison of actual and expected hash values.
......@@ -275,11 +293,12 @@ class HashMismatch(HashError):
"""
def hash_then_or(hash_name):
# type: (str) -> chain[str]
# For now, all the decent hashes have 6-char names, so we can get
# away with hard-coding space literals.
return chain([hash_name], repeat(' or'))
lines = []
lines = [] # type: List[str]
for hash_name, expecteds in iteritems(self.allowed):
prefix = hash_then_or(hash_name)
lines.extend((' Expected {} {}'.format(next(prefix), e))
......@@ -299,15 +318,17 @@ class ConfigurationFileCouldNotBeLoaded(ConfigurationError):
"""
def __init__(self, reason="could not be loaded", fname=None, error=None):
# type: (str, Optional[str], Optional[configparser.Error]) -> None
super(ConfigurationFileCouldNotBeLoaded, self).__init__(error)
self.reason = reason
self.fname = fname
self.error = error
def __str__(self):
# type: () -> str
if self.fname is not None:
message_part = " in {}.".format(self.fname)
else:
assert self.error is not None
message_part = ".\n{}\n".format(self.error.message)
message_part = ".\n{}\n".format(self.error)
return "Configuration file {}{}".format(self.reason, message_part)
# The following comment should be removed at some point in the future.
# mypy: disallow-untyped-defs=False
from __future__ import absolute_import
import datetime
......@@ -104,6 +101,7 @@ class SelfCheckState(object):
@property
def key(self):
# type: () -> str
return sys.prefix
def save(self, pypi_version, current_time):
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册