mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-04-08 04:34:16 +00:00
Add missing init hook
http://python-notes.curiousefficiency.org/en/latest/python_concepts/import_traps.html#the-init-py-trap
This commit is contained in:
parent
31853d6c43
commit
513a24cde9
5 changed files with 103 additions and 0 deletions
|
|
@ -64,6 +64,20 @@
|
||||||
entry: check-merge-conflict
|
entry: check-merge-conflict
|
||||||
language: python
|
language: python
|
||||||
types: [text]
|
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
|
- id: check-symlinks
|
||||||
name: Check for broken symlinks
|
name: Check for broken symlinks
|
||||||
description: Checks for symlinks which do not point to anything.
|
description: Checks for symlinks which do not point to anything.
|
||||||
|
|
|
||||||
|
|
@ -41,6 +41,7 @@ Add this to your `.pre-commit-config.yaml`
|
||||||
proper shebang.
|
proper shebang.
|
||||||
- `check-json` - Attempts to load all json files to verify syntax.
|
- `check-json` - Attempts to load all json files to verify syntax.
|
||||||
- `check-merge-conflict` - Check for files that contain merge conflict strings.
|
- `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-symlinks` - Checks for symlinks which do not point to anything.
|
||||||
- `check-toml` - Attempts to load all TOML files to verify syntax.
|
- `check-toml` - Attempts to load all TOML files to verify syntax.
|
||||||
- `check-vcs-permalinks` - Ensures that links to vcs websites are permalinks.
|
- `check-vcs-permalinks` - Ensures that links to vcs websites are permalinks.
|
||||||
|
|
|
||||||
25
pre_commit_hooks/check_missing_inits.py
Normal file
25
pre_commit_hooks/check_missing_inits.py
Normal 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())
|
||||||
|
|
@ -43,6 +43,7 @@ console_scripts =
|
||||||
check-executables-have-shebangs = pre_commit_hooks.check_executables_have_shebangs:main
|
check-executables-have-shebangs = pre_commit_hooks.check_executables_have_shebangs:main
|
||||||
check-json = pre_commit_hooks.check_json:main
|
check-json = pre_commit_hooks.check_json:main
|
||||||
check-merge-conflict = pre_commit_hooks.check_merge_conflict: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-symlinks = pre_commit_hooks.check_symlinks:main
|
||||||
check-toml = pre_commit_hooks.check_toml:main
|
check-toml = pre_commit_hooks.check_toml:main
|
||||||
check-vcs-permalinks = pre_commit_hooks.check_vcs_permalinks:main
|
check-vcs-permalinks = pre_commit_hooks.check_vcs_permalinks:main
|
||||||
|
|
|
||||||
62
tests/check_missing_inits_test.py
Normal file
62
tests/check_missing_inits_test.py
Normal 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
|
||||||
Loading…
Add table
Add a link
Reference in a new issue