import argparse import glob import os import plistlib import sys import subprocess from collections import defaultdict from whatchanged import directory_check_types, CheckType severity_mapping = { "kATSFontTestSeverityMinorError": "WARN", "kATSFontTestSeverityFatalError": "FAIL", "kATSFontTestSeverityInformation": "INFO", } default_levels = ["WARN", "FAIL"] def combine_severity(s1, s2): if s1 == "FAIL" or s2 == "FAIL": return "FAIL" if s1 == "WARN" or s2 == "WARN": return "WARN" return None def parse_ftxvalidator_report(contents): tree = plistlib.loads(contents) worst_severity = None for fonts in tree["kATSFontTestFontsTestedKey"]: font = fonts["kATSFontTestFontPostScriptNameKey"] results = fonts["kATSFontTestArrayKey"] for result in results: if not result["kATSFontTestResultKey"]: continue messages = result["kATSFontTestMessagesKey"] this_messages = defaultdict(list) for message in messages: messagetext = message["kATSFontTestMessageTextKey"] severity = severity_mapping.get(message["kATSFontTestResultKey"]) if severity not in default_levels: continue this_messages[severity].append(messagetext) if not this_messages: continue print(result["kATSFontTestIdentifierKey"]) for severity, messages in this_messages.items(): for message in messages: print(f" {severity}: {message}") worst_severity = combine_severity(worst_severity, severity) print() return worst_severity def main(): parser = argparse.ArgumentParser() parser.add_argument( "--branch", default="origin/main", help="branch to compare current head against" ) args = parser.parse_args() worst_severity = None for directory, check_type in directory_check_types(args.branch): if check_type not in [CheckType.NEW_FAMILY, CheckType.MODIFIED_FAMILY]: continue fonts = glob.glob(os.path.join(directory, "*.ttf")) for font in fonts: print(f"Validating {font}") result = subprocess.run( ["/Library/Apple/usr/bin/ftxvalidator", "-r", font], capture_output=True, text=False, check=True, ) worst_severity = combine_severity( worst_severity, parse_ftxvalidator_report(result.stdout) ) if worst_severity == "FAIL": sys.exit(1) if __name__ == "__main__": main()