mirror of
https://github.com/pre-commit/pre-commit-hooks.git
synced 2026-03-30 10:16:54 +00:00
70 lines
2 KiB
Python
70 lines
2 KiB
Python
from __future__ import annotations
|
|
|
|
import argparse
|
|
import json
|
|
import re
|
|
from typing import Any, Sequence
|
|
|
|
|
|
def raise_duplicate_keys(
|
|
ordered_pairs: list[tuple[str, Any]],
|
|
) -> dict[str, Any]:
|
|
d = {}
|
|
for key, val in ordered_pairs:
|
|
if key in d:
|
|
raise ValueError(f'Duplicate key: {key}')
|
|
else:
|
|
d[key] = val
|
|
return d
|
|
|
|
def check_mixed_indentation(content: str, filename: str) -> bool:
|
|
"""
|
|
Checks a string content for mixed indentation (tabs and spaces) in leading whitespace.
|
|
|
|
Args:
|
|
content (str): The content of the file to check.
|
|
filename (str): The name of the file being checked (for reporting purposes).
|
|
|
|
Returns:
|
|
bool: True if mixed indentation is found, False otherwise.
|
|
"""
|
|
found_mixed = False
|
|
|
|
for i, line in enumerate(content.splitlines(), 1):
|
|
# Determine leading whitespace
|
|
leading_whitespace = line[:len(line) - len(line.lstrip())]
|
|
|
|
# Check if both tabs and spaces are present in leading whitespace
|
|
if ' ' in leading_whitespace and '\t' in leading_whitespace:
|
|
print(f"{filename}: Mixed indentation (tabs and spaces) found on line {i}")
|
|
found_mixed = True
|
|
|
|
return not found_mixed
|
|
|
|
def main(argv: Sequence[str] | None = None) -> int:
|
|
parser = argparse.ArgumentParser()
|
|
parser.add_argument('filenames', nargs='*', help='Filenames to check.')
|
|
args = parser.parse_args(argv)
|
|
|
|
retval = 0
|
|
for filename in args.filenames:
|
|
with open(filename, 'r') as f:
|
|
content = f.read()
|
|
|
|
# Check for mixed indentation first
|
|
if not check_mixed_indentation(content, filename):
|
|
retval = 1
|
|
continue
|
|
|
|
# Then, attempt to parse the JSON
|
|
try:
|
|
json.loads(content, object_pairs_hook=raise_duplicate_keys)
|
|
except ValueError as exc:
|
|
print(f'{filename}: Failed to json decode ({exc})')
|
|
retval = 1
|
|
|
|
return retval
|
|
|
|
|
|
if __name__ == '__main__':
|
|
raise SystemExit(main())
|