pre-commit-hooks/pre_commit_hooks/end_of_file_fixer.py
2021-09-28 23:38:05 +02:00

60 lines
1.6 KiB
Python

import argparse
from typing import Optional
from typing import Sequence
def _process_file(file_obj: bytes) -> bytes:
# Test for newline at end of file
# Empty files will throw IOError here
while len(file_obj):
if file_obj[-2:] == b'\r\n':
if len(file_obj) == 2:
return b''
elif file_obj[-3:-2] not in {b'\n', b'\r'}:
return file_obj
else:
file_obj = file_obj[:-2]
elif file_obj[-1:] in {b'\n', b'\r'}:
if len(file_obj) == 1:
return b''
elif file_obj[-2:-1] not in {b'\n', b'\r'}:
return file_obj
else:
file_obj = file_obj[:-1]
else:
return file_obj + b'\n'
return file_obj
def _fix_file(filename: str) -> bool:
with open(filename, mode='rb') as file_processed:
file_content = file_processed.read()
newcontent = _process_file(file_content)
if newcontent != file_content:
with open(filename, mode='wb') as file_processed:
file_processed.write(newcontent)
return True
else:
return False
def main(argv: Optional[Sequence[str]] = None) -> int:
parser = argparse.ArgumentParser()
parser.add_argument('filenames', nargs='*', help='Filenames to fix')
args = parser.parse_args(argv)
retv = 0
for filename in args.filenames:
# Read as binary so we can read byte-by-byte
if _fix_file(filename):
print(f'Fixing {filename}')
retv = 1
return retv
if __name__ == '__main__':
exit(main())