Sam Park 2020-01-18 11:29:05 -08:00
parent 31853d6c43
commit 513a24cde9
No known key found for this signature in database
GPG key ID: 5CA023C8A1C73D5F
5 changed files with 103 additions and 0 deletions

View file

@ -64,6 +64,20 @@
entry: check-merge-conflict
language: python
types: [text]
- id: check-missing-inits
name: Find directories with missing __init__ files
description: |-
Verify that all Python directories contain an __init__.py
Although __init__.py files are not required on Python 3.3+, omitting them in
one directory while having them in another directory will break in confusing
and unexpected ways:
http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-init-py-trap
entry: check-missing-inits
language: python
require_serial: true
files: .*\.py$
- id: check-symlinks
name: Check for broken symlinks
description: Checks for symlinks which do not point to anything.

View file

@ -41,6 +41,7 @@ Add this to your `.pre-commit-config.yaml`
proper shebang.
- `check-json` - Attempts to load all json files to verify syntax.
- `check-merge-conflict` - Check for files that contain merge conflict strings.
- `check-missing-inits` - Checks for missing `__init__.py` files in any directory containing Python files.
- `check-symlinks` - Checks for symlinks which do not point to anything.
- `check-toml` - Attempts to load all TOML files to verify syntax.
- `check-vcs-permalinks` - Ensures that links to vcs websites are permalinks.

View file

@ -0,0 +1,25 @@
import os
from argparse import ArgumentParser
from typing import Optional
from typing import Sequence
def main(argv=None): # type: (Optional[Sequence[str]]) -> int
parser = ArgumentParser()
parser.add_argument('filenames', nargs='*', help='Filenames to check')
args = parser.parse_args(argv)
directories = {os.path.dirname(f) for f in args.filenames}
missing_dirs = set()
for d in directories:
if not os.path.exists(os.path.join(d, '__init__.py')):
missing_dirs.add(d)
for d in sorted(missing_dirs):
print('No __init__.py file found in: {}'.format(d))
return 1 if len(missing_dirs) else 0
if __name__ == '__main__':
exit(main())

View file

@ -43,6 +43,7 @@ console_scripts =
check-executables-have-shebangs = pre_commit_hooks.check_executables_have_shebangs:main
check-json = pre_commit_hooks.check_json:main
check-merge-conflict = pre_commit_hooks.check_merge_conflict:main
check-missing-inits = pre_commit_hooks.check_missing_inits:main
check-symlinks = pre_commit_hooks.check_symlinks:main
check-toml = pre_commit_hooks.check_toml:main
check-vcs-permalinks = pre_commit_hooks.check_vcs_permalinks:main

View file

@ -0,0 +1,62 @@
import os
import pytest
from pre_commit_hooks.check_missing_inits import main
@pytest.fixture
def filepaths(tmpdir):
dirs = ['a', 'b']
files = ['a.py', 'b.py', '__init__.py']
paths = []
for d in dirs:
directory = tmpdir / d
os.mkdir(str(directory))
for f in files:
path = (directory / f)
paths.append(str(path))
# Nested directory
if d == 'b':
directory = directory / 'c'
os.mkdir(str(directory))
for f in files:
path = (directory / f)
paths.append(str(path))
return paths
def test_has_inits(filepaths):
for f in filepaths:
with open(f, 'w'):
pass
assert main(argv=filepaths) == 0
def test_missing_inits(filepaths):
remove = ''
for f in filepaths:
# Remove the init py file from the b directory
if os.path.join('b', '__init__.py') in f:
remove = str(f)
continue
with open(f, 'w'):
pass
filepaths.remove(remove)
assert main(argv=filepaths) == 1
def test_nested_dirs_missing_inits(filepaths):
remove = ''
for f in filepaths:
# Remove the init py file from a nested directory
if os.path.join('b', 'c', '__init__.py') in f:
remove = str(f)
continue
with open(f, 'w'):
pass
filepaths.remove(remove)
assert main(argv=filepaths) == 1