Skip to content

Commit 8ea5116

Browse files
committed
FIX: make the xml formatter try several times in one run to avoid needing to re-run it again.
1 parent eb611da commit 8ea5116

1 file changed

Lines changed: 37 additions & 9 deletions

File tree

pre_commit_hooks/xml_format.py

Lines changed: 37 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,16 +1,47 @@
11
#!C:/miniconda/envs/plc-pre-commit/python.exe
22

33
import argparse
4+
45
from lxml import etree
56

67
TAB_WIDTH = 2
8+
RETRIES = 5
79

810

9-
def fix_file(filename, tab_width=TAB_WIDTH):
11+
def fix_file(
12+
filename: str,
13+
tab_width: int = TAB_WIDTH,
14+
retries: int = RETRIES,
15+
) -> None:
16+
"""
17+
Read a file, fix it, write the fix back to the file handle
18+
"""
1019
# lxml throws encoding errors unless we work in binary mode
11-
with open(filename, 'rb') as fd:
20+
with open(filename, "rb") as fd:
1221
original_xml = fd.read()
22+
iter_xml = original_xml
23+
24+
for _ in range(retries):
25+
new_xml = xml_once(
26+
original_xml=iter_xml,
27+
tab_width=tab_width,
28+
)
29+
if new_xml == iter_xml:
30+
break
31+
iter_xml = new_xml
32+
33+
if new_xml != original_xml:
34+
print(f"Fixing {filename}")
35+
with open(filename, "wb") as fd:
36+
fd.write(new_xml)
1337

38+
39+
def xml_once(original_xml: str, tab_width: int) -> str:
40+
"""
41+
One iteration of the xml formatting.
42+
43+
This may need to run several times due to inconsistencies in lxml.
44+
"""
1445
# lxml is the easiest cross-platform way to do this using pre-commit
1546
# xmllint is cross-platform but pre-commit does not help us set it up
1647
xml_parser = etree.XMLParser(remove_blank_text=True)
@@ -25,18 +56,15 @@ def fix_file(filename, tab_width=TAB_WIDTH):
2556
# lxml always outputs with unix line endings (LF)
2657
if b'\r\n' in original_xml:
2758
new_xml = new_xml.replace(b'\n', b'\r\n')
28-
29-
if new_xml != original_xml:
30-
print(f'Fixing {filename}')
31-
with open(filename, 'wb') as fd:
32-
fd.write(new_xml)
59+
return new_xml
3360

3461

3562
def main(args=None):
3663
if args is None:
3764
parser = argparse.ArgumentParser()
38-
parser.add_argument('filenames', nargs='*')
39-
parser.add_argument('--tab-width', type=int, default=TAB_WIDTH)
65+
parser.add_argument("filenames", nargs="*")
66+
parser.add_argument("--tab-width", type=int, default=TAB_WIDTH)
67+
parser.add_argument("--retries", type=int, default=RETRIES)
4068
args = parser.parse_args()
4169
try:
4270
for filename in args.filenames:

0 commit comments

Comments
 (0)