Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
0f9d259
Add basic mypy support
pradyunsg Jun 14, 2017
bc637a8
:newspaper:
pradyunsg Jun 16, 2017
ed9208e
Improve mypy configuration
pradyunsg Jun 14, 2017
9fce241
Patch pkg_resources for mypy
pradyunsg Jun 15, 2017
8f92b55
Fix mypy warnings
pradyunsg Jun 15, 2017
da46ab2
Add type annotations to pip.configuration
pradyunsg Jun 15, 2017
711596b
Use pip.utils.typing to guard typing imports
pradyunsg Jun 16, 2017
7c5f901
Modify vendoring to include additional .pyi stubs
pradyunsg Jul 4, 2017
adf4538
Add generated stubs
pradyunsg Jul 4, 2017
c2371a1
Exclude the pyi files and extra directory created
pradyunsg Jul 4, 2017
b3e16f9
Fix mypy errors since addition of stubs
pradyunsg Jul 17, 2017
55fd83f
Add a separate tox job for mypy
pradyunsg Jul 17, 2017
6a0da3d
Fix a bug found by mypy
pradyunsg Jul 17, 2017
9b03434
use six instead of try except
pradyunsg Jul 17, 2017
3046f7a
Don't ask for permission
pradyunsg Jul 17, 2017
182c548
Fix remaining errors
pradyunsg Jul 17, 2017
b9b5e4a
:art:
pradyunsg Jul 17, 2017
1b5a23f
:wrench:
pradyunsg Jul 17, 2017
c365304
Merge branch 'master' into mypy/infrastructure
pradyunsg Aug 2, 2017
cb113d5
I actually missed a conflict. Wow.
pradyunsg Aug 2, 2017
11451c5
Merge branch 'master' into mypy/infrastructure
pradyunsg Sep 2, 2017
d37868f
Move the typing file
pradyunsg Sep 2, 2017
d408818
Add imports I'd missed
pradyunsg Sep 2, 2017
d9a4431
Move mypy stubs as well
pradyunsg Sep 2, 2017
efd7264
Update MANIFEST
pradyunsg Sep 2, 2017
ec26f0a
Import from inner packages
pradyunsg Sep 2, 2017
da57810
type: Any partials in cmdoptions
pradyunsg Sep 2, 2017
93d9f20
Remove a useless section
pradyunsg Sep 2, 2017
e2b2f70
isort all imports
pradyunsg Sep 2, 2017
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,7 @@ pip.egg-info/
MANIFEST
.tox
.cache
.mypy_cache
*.egg
*.eggs
*.py[cod]
Expand Down
1 change: 1 addition & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@ matrix:
- env: TOXENV=docs
- env: TOXENV=lint-py2
- env: TOXENV=lint-py3
- env: TOXENV=mypy
- env: TOXENV=packaging
# PyPy jobs start first -- they are the slowest
- env: TOXENV=pypy
Expand Down
3 changes: 3 additions & 0 deletions MANIFEST.in
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,9 @@ exclude appveyor.yml
recursive-include src/pip/_vendor *.pem
recursive-include docs Makefile *.rst *.py *.bat

exclude src/pip/_vendor/six
recursive-exclude src/pip/_vendor *.pyi

prune .github
prune .travis
prune docs/_build
Expand Down
1 change: 1 addition & 0 deletions news/4545.feature
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
Integrate with mypy for utilizing static typing.
10 changes: 10 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
Expand Up @@ -11,9 +11,19 @@ known_first_party =
default_section = THIRDPARTY

[flake8]
# Ignoring unused imports since mypy would warn of that.
ignore = F401
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sorry I've been quite busy these last months so I'm a little late in my review ^^
Couldn't we tag the unused imports specifically and keep this check in flake8 ?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

flake8 doesn't actually understand the mypy declarations and shouts about them. mypy (obviously) does and doesn't shout about valid usage.

IIRC, I remember reading somewhere in the mypy documentation that it does detect if a certain import is unused, which is what made me feel comfortable about silencing these warnings. Now that both linters are run one after another, I don't think it's an issue if mypy catches something instead of flake8.

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Oh, and I had looked at https://github.com/ambv/flake8-mypy -- The first line of the description of that project makes me think this approach is better suited.

Further, the "Two levels of type checking" section of that project's README motivated me to actually take this route.

exclude = .tox,.idea,*.egg,build,_vendor,data
select = E,W,F

[mypy]
follow_imports = silent
ignore_missing_imports = True

[mypy-pip/_vendor/*]
follow_imports = skip
ignore_errors = True

[tool:pytest]
addopts = --ignore src/pip/_vendor --ignore tests/tests_cache

Expand Down
11 changes: 1 addition & 10 deletions src/pip/_internal/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -55,15 +55,6 @@
InsecureRequestWarning,
)


# assignment for flake8 to be happy

# This fixes a peculiarity when importing via __import__ - as we are
# initialising the pip module, "from pip import cmdoptions" is recursive
# and appears not to work properly in that situation.
# import pip._internal.cmdoptions
# cmdoptions = pip._internal.cmdoptions

logger = logging.getLogger(__name__)

# Hide the InsecureRequestWarning from urllib3
Expand Down Expand Up @@ -241,7 +232,7 @@ def main(args=None):
sys.exit(1)

# Needed for locale.getpreferredencoding(False) to work
# in pip.utils.encoding.auto_decode
# in pip._internal.utils.encoding.auto_decode
try:
locale.setlocale(locale.LC_ALL, '')
except locale.Error as e:
Expand Down
16 changes: 10 additions & 6 deletions src/pip/_internal/basecommand.py
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,8 @@
)
from pip._internal.index import PackageFinder
from pip._internal.locations import running_under_virtualenv
from pip._internal.req import InstallRequirement, parse_requirements
from pip._internal.req.req_file import parse_requirements
from pip._internal.req.req_install import InstallRequirement
from pip._internal.status_codes import (
ERROR, PREVIOUS_BUILD_DIR_ERROR, SUCCESS, UNKNOWN_ERROR,
VIRTUALENV_NOT_FOUND
Expand All @@ -29,18 +30,21 @@
from pip._internal.utils.logging import IndentingFormatter
from pip._internal.utils.misc import get_prog, normalize_path
from pip._internal.utils.outdated import pip_version_check
from pip._internal.utils.typing import MYPY_CHECK_RUNNING

__all__ = ['Command']
if MYPY_CHECK_RUNNING:
from typing import Optional

__all__ = ['Command']

logger = logging.getLogger(__name__)


class Command(object):
name = None
usage = None
hidden = False
ignore_require_venv = False
name = None # type: Optional[str]
usage = None # type: Optional[str]
hidden = False # type: bool
ignore_require_venv = False # type: bool
log_streams = ("ext://sys.stdout", "ext://sys.stderr")

def __init__(self, isolated=False):
Expand Down
Loading