Skip to content

Commit 804a8e4

Browse files
rtibblesbotclaude
andcommitted
fix: normalize downloaded schema encoding and run pre-commit in refresh_schema
XInclude.xsd is served by purl.imsglobal.org as UTF-16 with no XML declaration, unlike every other vendored source (plain UTF-8). Re-running the script always produced a binary diff on that one file. Transcode any UTF-16 download to UTF-8 (preserving formatting rather than reflowing via lxml) and run the repo's trailing-whitespace/end-of-file-fixer hooks on the vendored tree after download, matching what was applied to the committed copies. Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
1 parent c07cfc6 commit 804a8e4

1 file changed

Lines changed: 32 additions & 1 deletion

File tree

contentcuration/contentcuration/utils/assessment/qti/schema/refresh_schema.py

Lines changed: 32 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,9 @@
1111
1212
pytest contentcuration/contentcuration/tests/utils/qti/test_validation.py -v
1313
"""
14+
import codecs
1415
import socket
16+
import subprocess
1517
from pathlib import Path
1618

1719
import requests
@@ -47,12 +49,28 @@
4749
}
4850

4951

52+
def _normalize_encoding(content):
53+
# purl.imsglobal.org serves XInclude.xsd as UTF-16 with no XML declaration,
54+
# unlike every other source file here (plain UTF-8); transcode rather than
55+
# leaving it as the only non-UTF-8, non-diffable file in the vendored tree.
56+
# Decoding/re-encoding (instead of round-tripping through lxml) preserves
57+
# the original formatting instead of reflowing it.
58+
if content.startswith(codecs.BOM_UTF16_LE) or content.startswith(
59+
codecs.BOM_UTF16_BE
60+
):
61+
text = content.decode("utf-16")
62+
if not text.lstrip().startswith("<?xml"):
63+
text = '<?xml version="1.0" encoding="UTF-8"?>\n' + text
64+
return text.encode("utf-8")
65+
return content
66+
67+
5068
def download():
5169
XSD_DIR.mkdir(parents=True, exist_ok=True)
5270
for filename, url in SOURCES.items():
5371
response = requests.get(url, timeout=30)
5472
response.raise_for_status()
55-
(XSD_DIR / filename).write_bytes(response.content)
73+
(XSD_DIR / filename).write_bytes(_normalize_encoding(response.content))
5674

5775

5876
def rewrite_schema_locations():
@@ -67,6 +85,18 @@ def rewrite_schema_locations():
6785
path.write_text(text)
6886

6987

88+
def run_pre_commit():
89+
# Applies the repo's trailing-whitespace/end-of-file-fixer hooks (the only
90+
# hooks whose `files:` patterns match .xsd) so the vendored tree matches
91+
# the same convention already applied to the committed copies. Exit code
92+
# 1 just means files were modified; that's expected, not a failure.
93+
subprocess.run(
94+
["pre-commit", "run", "--files"]
95+
+ [str(path) for path in sorted(XSD_DIR.glob("*.xsd"))],
96+
check=False,
97+
)
98+
99+
70100
def verify_compiles_offline():
71101
real_socket = socket.socket
72102

@@ -83,6 +113,7 @@ def _blocked(*args, **kwargs):
83113
def main():
84114
download()
85115
rewrite_schema_locations()
116+
run_pre_commit()
86117
verify_compiles_offline()
87118
print("Vendored schema refreshed in %s" % XSD_DIR) # noqa: T201
88119

0 commit comments

Comments
 (0)