Skip to content

Commit

Permalink
Apply typing to all of pre-commit-hooks
Browse files Browse the repository at this point in the history
  • Loading branch information
asottile committed Feb 1, 2019
1 parent 63cc341 commit 5107807
Show file tree
Hide file tree
Showing 54 changed files with 398 additions and 263 deletions.
9 changes: 2 additions & 7 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,16 +1,11 @@
*.egg-info
*.iml
*.py[co]
.*.sw[a-z]
.pytest_cache
.coverage
.idea
.project
.pydevproject
.tox
.venv.touch
/.mypy_cache
/.pytest_cache
/venv*
coverage-html
dist
# SublimeText project/workspace files
*.sublime-*
7 changes: 6 additions & 1 deletion .pre-commit-config.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ repos:
rev: v1.3.5
hooks:
- id: reorder-python-imports
language_version: python2.7
language_version: python3
- repo: https://github.com/asottile/pyupgrade
rev: v1.11.1
hooks:
Expand All @@ -36,3 +36,8 @@ repos:
rev: v0.7.1
hooks:
- id: add-trailing-comma
- repo: https://github.com/pre-commit/mirrors-mypy
rev: v0.660
hooks:
- id: mypy
language_version: python3
4 changes: 2 additions & 2 deletions .travis.yml
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
dist: xenial
language: python
matrix:
include: # These should match the tox env list
Expand All @@ -6,9 +7,8 @@ matrix:
python: 3.6
- env: TOXENV=py37
python: 3.7
dist: xenial
- env: TOXENV=pypy
python: pypy-5.7.1
python: pypy2.7-5.10.0
install: pip install coveralls tox
script: tox
before_install:
Expand Down
9 changes: 5 additions & 4 deletions get-git-lfs.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,7 @@
import os.path
import shutil
import tarfile
from urllib.request import urlopen
import urllib.request

DOWNLOAD_PATH = (
'https://github.com/github/git-lfs/releases/download/'
Expand All @@ -15,7 +15,7 @@
DEST_DIR = os.path.dirname(DEST_PATH)


def main():
def main(): # type: () -> int
if (
os.path.exists(DEST_PATH) and
os.path.isfile(DEST_PATH) and
Expand All @@ -27,12 +27,13 @@ def main():
shutil.rmtree(DEST_DIR, ignore_errors=True)
os.makedirs(DEST_DIR, exist_ok=True)

contents = io.BytesIO(urlopen(DOWNLOAD_PATH).read())
contents = io.BytesIO(urllib.request.urlopen(DOWNLOAD_PATH).read())
with tarfile.open(fileobj=contents) as tar:
with tar.extractfile(PATH_IN_TAR) as src_file:
with tar.extractfile(PATH_IN_TAR) as src_file: # type: ignore
with open(DEST_PATH, 'wb') as dest_file:
shutil.copyfileobj(src_file, dest_file)
os.chmod(DEST_PATH, 0o755)
return 0


if __name__ == '__main__':
Expand Down
12 changes: 12 additions & 0 deletions mypy.ini
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
[mypy]
check_untyped_defs = true
disallow_any_generics = true
disallow_incomplete_defs = true
disallow_untyped_defs = true
no_implicit_optional = true

[mypy-testing.*]
disallow_untyped_defs = false

[mypy-tests.*]
disallow_untyped_defs = false
2 changes: 1 addition & 1 deletion pre_commit_hooks/autopep8_wrapper.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,7 @@
from __future__ import unicode_literals


def main(argv=None):
def main(): # type: () -> int
raise SystemExit(
'autopep8-wrapper is deprecated. Instead use autopep8 directly via '
'https://github.com/pre-commit/mirrors-autopep8',
Expand Down
9 changes: 7 additions & 2 deletions pre_commit_hooks/check_added_large_files.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,13 +7,17 @@
import json
import math
import os
from typing import Iterable
from typing import Optional
from typing import Sequence
from typing import Set

from pre_commit_hooks.util import added_files
from pre_commit_hooks.util import CalledProcessError
from pre_commit_hooks.util import cmd_output


def lfs_files():
def lfs_files(): # type: () -> Set[str]
try:
# Introduced in git-lfs 2.2.0, first working in 2.2.1
lfs_ret = cmd_output('git', 'lfs', 'status', '--json')
Expand All @@ -24,6 +28,7 @@ def lfs_files():


def find_large_added_files(filenames, maxkb):
# type: (Iterable[str], int) -> int
# Find all added files that are also in the list of files pre-commit tells
# us about
filenames = (added_files() & set(filenames)) - lfs_files()
Expand All @@ -38,7 +43,7 @@ def find_large_added_files(filenames, maxkb):
return retv


def main(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument(
'filenames', nargs='*',
Expand Down
6 changes: 4 additions & 2 deletions pre_commit_hooks/check_ast.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,9 +7,11 @@
import platform
import sys
import traceback
from typing import Optional
from typing import Sequence


def check_ast(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*')
args = parser.parse_args(argv)
Expand All @@ -34,4 +36,4 @@ def check_ast(argv=None):


if __name__ == '__main__':
exit(check_ast())
exit(main())
34 changes: 20 additions & 14 deletions pre_commit_hooks/check_builtin_literals.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,6 +4,10 @@
import ast
import collections
import sys
from typing import List
from typing import Optional
from typing import Sequence
from typing import Set


BUILTIN_TYPES = {
Expand All @@ -22,14 +26,17 @@

class BuiltinTypeVisitor(ast.NodeVisitor):
def __init__(self, ignore=None, allow_dict_kwargs=True):
self.builtin_type_calls = []
# type: (Optional[Sequence[str]], bool) -> None
self.builtin_type_calls = [] # type: List[BuiltinTypeCall]
self.ignore = set(ignore) if ignore else set()
self.allow_dict_kwargs = allow_dict_kwargs

def _check_dict_call(self, node):
def _check_dict_call(self, node): # type: (ast.Call) -> bool

return self.allow_dict_kwargs and (getattr(node, 'kwargs', None) or getattr(node, 'keywords', None))

def visit_Call(self, node):
def visit_Call(self, node): # type: (ast.Call) -> None

if not isinstance(node.func, ast.Name):
# Ignore functions that are object attributes (`foo.bar()`).
# Assume that if the user calls `builtins.list()`, they know what
Expand All @@ -47,31 +54,30 @@ def visit_Call(self, node):


def check_file_for_builtin_type_constructors(filename, ignore=None, allow_dict_kwargs=True):
# type: (str, Optional[Sequence[str]], bool) -> List[BuiltinTypeCall]
with open(filename, 'rb') as f:
tree = ast.parse(f.read(), filename=filename)
visitor = BuiltinTypeVisitor(ignore=ignore, allow_dict_kwargs=allow_dict_kwargs)
visitor.visit(tree)
return visitor.builtin_type_calls


def parse_args(argv):
def parse_ignore(value):
return set(value.split(','))
def parse_ignore(value): # type: (str) -> Set[str]
return set(value.split(','))


def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*')
parser.add_argument('--ignore', type=parse_ignore, default=set())

allow_dict_kwargs = parser.add_mutually_exclusive_group(required=False)
allow_dict_kwargs.add_argument('--allow-dict-kwargs', action='store_true')
allow_dict_kwargs.add_argument('--no-allow-dict-kwargs', dest='allow_dict_kwargs', action='store_false')
allow_dict_kwargs.set_defaults(allow_dict_kwargs=True)

return parser.parse_args(argv)
mutex = parser.add_mutually_exclusive_group(required=False)
mutex.add_argument('--allow-dict-kwargs', action='store_true')
mutex.add_argument('--no-allow-dict-kwargs', dest='allow_dict_kwargs', action='store_false')
mutex.set_defaults(allow_dict_kwargs=True)

args = parser.parse_args(argv)

def main(argv=None):
args = parse_args(argv)
rc = 0
for filename in args.filenames:
calls = check_file_for_builtin_type_constructors(
Expand Down
4 changes: 3 additions & 1 deletion pre_commit_hooks/check_byte_order_marker.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,9 +3,11 @@
from __future__ import unicode_literals

import argparse
from typing import Optional
from typing import Sequence


def main(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*', help='Filenames to check')
args = parser.parse_args(argv)
Expand Down
10 changes: 7 additions & 3 deletions pre_commit_hooks/check_case_conflict.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,20 @@
from __future__ import unicode_literals

import argparse
from typing import Iterable
from typing import Optional
from typing import Sequence
from typing import Set

from pre_commit_hooks.util import added_files
from pre_commit_hooks.util import cmd_output


def lower_set(iterable):
def lower_set(iterable): # type: (Iterable[str]) -> Set[str]
return {x.lower() for x in iterable}


def find_conflicting_filenames(filenames):
def find_conflicting_filenames(filenames): # type: (Sequence[str]) -> int
repo_files = set(cmd_output('git', 'ls-files').splitlines())
relevant_files = set(filenames) | added_files()
repo_files -= relevant_files
Expand Down Expand Up @@ -41,7 +45,7 @@ def find_conflicting_filenames(filenames):
return retv


def main(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument(
'filenames', nargs='*',
Expand Down
5 changes: 4 additions & 1 deletion pre_commit_hooks/check_docstring_first.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,6 +5,8 @@
import argparse
import io
import tokenize
from typing import Optional
from typing import Sequence


NON_CODE_TOKENS = frozenset((
Expand All @@ -13,6 +15,7 @@


def check_docstring_first(src, filename='<unknown>'):
# type: (str, str) -> int
"""Returns nonzero if the source has what looks like a docstring that is
not at the beginning of the source.
Expand Down Expand Up @@ -50,7 +53,7 @@ def check_docstring_first(src, filename='<unknown>'):
return 0


def main(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*')
args = parser.parse_args(argv)
Expand Down
10 changes: 8 additions & 2 deletions pre_commit_hooks/check_executables_have_shebangs.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,11 @@
import argparse
import pipes
import sys
from typing import Optional
from typing import Sequence


def check_has_shebang(path):
def check_has_shebang(path): # type: (str) -> int
with open(path, 'rb') as f:
first_bytes = f.read(2)

Expand All @@ -27,7 +29,7 @@ def check_has_shebang(path):
return 0


def main(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser(description=__doc__)
parser.add_argument('filenames', nargs='*')
args = parser.parse_args(argv)
Expand All @@ -38,3 +40,7 @@ def main(argv=None):
retv |= check_has_shebang(filename)

return retv


if __name__ == '__main__':
exit(main())
6 changes: 4 additions & 2 deletions pre_commit_hooks/check_json.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,9 +4,11 @@
import io
import json
import sys
from typing import Optional
from typing import Sequence


def check_json(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*', help='JSON filenames to check.')
args = parser.parse_args(argv)
Expand All @@ -22,4 +24,4 @@ def check_json(argv=None):


if __name__ == '__main__':
sys.exit(check_json())
sys.exit(main())
9 changes: 6 additions & 3 deletions pre_commit_hooks/check_merge_conflict.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,9 @@

import argparse
import os.path
from typing import Optional
from typing import Sequence


CONFLICT_PATTERNS = [
b'<<<<<<< ',
Expand All @@ -12,7 +15,7 @@
WARNING_MSG = 'Merge conflict string "{0}" found in {1}:{2}'


def is_in_merge():
def is_in_merge(): # type: () -> int
return (
os.path.exists(os.path.join('.git', 'MERGE_MSG')) and
(
Expand All @@ -23,7 +26,7 @@ def is_in_merge():
)


def detect_merge_conflict(argv=None):
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*')
parser.add_argument('--assume-in-merge', action='store_true')
Expand All @@ -47,4 +50,4 @@ def detect_merge_conflict(argv=None):


if __name__ == '__main__':
exit(detect_merge_conflict())
exit(main())
Loading

0 comments on commit 5107807

Please sign in to comment.