From c2564d010c39478ce1de54d24d7801d47934a1d0 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Mon, 30 Oct 2023 13:59:15 +0000 Subject: [PATCH 01/10] wip ninja refactor --- src/diffenator2/__init__.py | 357 ++++++++++++------------------- src/diffenator2/__main__.py | 38 +--- src/diffenator2/_diffbrowsers.py | 3 +- src/diffenator2/_diffenator.py | 2 +- 4 files changed, 141 insertions(+), 259 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index c629901..e072599 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -7,6 +7,7 @@ from diffenator2.font import DFont, get_font_styles from diffenator2.utils import partition from diffenator2.matcher import FontMatcher +import shutil import ninja logger = logging.getLogger(__name__) @@ -18,240 +19,148 @@ NINJA_BUILD_FILE = "build.ninja" -def ninja_proof( - fonts: list[DFont], - out: str = "out", - imgs: bool = False, - styles="instances", - filter_styles: str = "", - characters: str = ".*", - pt_size: int = 20, - user_wordlist: str = "", -): - if not os.path.exists(out): - os.mkdir(out) - - if filter_styles: - _ninja_proof(fonts, out, imgs, styles, filter_styles, characters, pt_size, user_wordlist) - return - - font_styles = get_font_styles(fonts, styles) - partitioned = partition(font_styles, MAX_STYLES) - for font_styles in partitioned: - filter_styles = "|".join(s.name for s in font_styles) - o = os.path.join(out, filter_styles.replace("|", "-")) - if not os.path.exists(o): - os.mkdir(o) - _ninja_proof(fonts, o, imgs, styles, filter_styles, characters, pt_size, user_wordlist) - - -def _ninja_proof( - fonts: list[DFont], - out: str = "out", - imgs: bool = False, - styles: str = "instances", - filter_styles: str = "", - characters=".*", - pt_size: int = 20, - user_wordlist = "", -): - w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - w.comment("Rules") - w.newline() - out_s = os.path.join("out", "diffbrowsers") - - cmd = f'_diffbrowsers proof $fonts -s $styles -o $out -pt $pt_size -ch "$characters"' - if imgs: - cmd += " --imgs" - if filter_styles: - cmd += f' --filter-styles "$filters"' - if user_wordlist: - cmd += f' --user-wordlist "$user_wordlist"' - w.rule("proofing", cmd) - w.newline() - - # Setup build - w.comment("Build rules") - variables = dict( - fonts=[f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts], - styles=styles, - out=out_s, - pt_size=pt_size, - characters=characters, - ) - if imgs: - variables["imgs"] = imgs - if filter_styles: - variables["filters"] = filter_styles - if user_wordlist: - variables["user_wordlist"] = user_wordlist - w.build(out, "proofing", variables=variables) - w.close() - ninja._program("ninja", []) - - -def ninja_diff( - fonts_before: list[DFont], - fonts_after: list[DFont], - diffbrowsers: bool = True, - diffenator: bool = True, - out: str = "out", - imgs: bool = False, - styles: str = "instances", - characters: str = ".*", - user_wordlist: str = "", - filter_styles: str = "", - pt_size: int = 20, - threshold: float = THRESHOLD, - precision: int = FONT_SIZE, - no_words: bool = False, - no_tables: bool = False, -): - if not os.path.exists(out): - os.mkdir(out) - - if filter_styles: - _ninja_diff( - fonts_before, - fonts_after, - diffbrowsers, - diffenator, - out, - imgs, - styles, - characters, - user_wordlist, - filter_styles, - pt_size, - threshold=threshold, - precision=precision, - no_words=no_words, - no_tables=no_tables, +class NinjaBuilder: + NINJA_LOG_FILE = ".ninja_log" + NINJA_BUILD_FILE = "build.ninja" + + def __init__(self, **kwargs): + for k, v in kwargs.items(): + setattr(self, k, v) + self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) + + def add_rule(self, name, string): + cmd = self.populate_cli_command(string) + self.w.comment("Rules") + self.w.newline() + self.w.rule(name, cmd) + self.w.newline() + + def build(self, out, name, varss): + # Setup build + self.w.comment("Build rules") + variables = { + **{k: v for k, v in self.__dict__.items() if k not in ["command", "w"]}, + **varss, + } + self.w.build(out, name, variables=variables) + + def run(self): + self.w.close() + ninja._program("ninja", []) + + def proof_fonts(self, fonts): + self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) + self.add_rule("proofing", "_diffbrowsers proof $fonts") + varss = { + "fonts": [f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts] + } + self.build("proofing", varss) + self.run() + + def diff_fonts(self, fonts_before, fonts_after): + self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) + self.add_rule( + "diffbrowsers", "_diffbrowsers diff -fb $fonts_before -fa $fonts_after" ) - return - - matcher = FontMatcher(fonts_before, fonts_after) - getattr(matcher, styles)() + varss = { + "fonts_before": [ + f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_before + ], + "fonts_after": [ + f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_after + ], + } + self.build(self.out, "diffbrowsers", varss) + + self.add_rule( + "diffenator", "_diffenator $font_before $font_after" + ) + + matcher = FontMatcher(fonts_before, fonts_after) + getattr(matcher, self.styles)(self.filter_styles) + for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): + coords = new_style.coords + style = new_style.name.replace(" ", "-") + diff_vars = { + "font_before": f'"{old_style.font.ttFont.reader.file.name}"', + "font_after": f'"{new_style.font.ttFont.reader.file.name}"', + } + # Fix this shit + self.fonts_before = None + self.fonts_after = None + o = os.path.join(self.out, style.replace(" ", "-")) + self.build(o, "diffenator", diff_vars) + self.run() + + def populate_cli_command(self, cmd): + for k, v in vars(self).items(): + k = k.replace("_", "-") + if any([not v, k == "w", k == "command"]): + continue + elif isinstance(v, bool): + cmd += f" --{k}" + elif isinstance(v, (str, int, float)): + cmd += f' --{k} "${k}"' + return cmd + + def __enter__(self): + return self + + def __exit__(self, exc_type, exc_val, exc_tb): + # rm ninja cache files so we can rerun the tool + if os.path.exists(self.NINJA_BUILD_FILE): + os.remove(self.NINJA_BUILD_FILE) + if os.path.exists(self.NINJA_LOG_FILE): + os.remove(self.NINJA_LOG_FILE) + + +def ninja_proof(**kwargs): + if not os.path.exists(kwargs["out"]): + os.mkdir(kwargs["out"]) + + with NinjaBuilder(**kwargs) as builder: + if kwargs["filter_styles"]: + builder.proof_fonts(kwargs["fonts"]) + return + + font_styles = get_font_styles(kwargs["fonts"], kwargs["styles"]) + partitioned = partition(font_styles, MAX_STYLES) + for font_styles in partitioned: + filter_styles = "|".join(s.name for s in font_styles) + o = os.path.join(kwargs["out"], filter_styles.replace("|", "-")) + if not os.path.exists(o): + os.mkdir(o) + builder.out = o + builder.filter_styles = filter_styles + builder.proof_fonts(kwargs["fonts"]) + + +def ninja_diff(**kwargs): + if not os.path.exists(kwargs["out"]): + os.mkdir(kwargs["out"]) + + with NinjaBuilder(**kwargs) as builder: + if kwargs["filter_styles"]: + builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) + return + + matcher = FontMatcher(kwargs["fonts_before"], kwargs["fonts_after"]) + getattr(matcher, kwargs["styles"])() if not matcher.old_styles and not matcher.new_styles: raise ValueError( - f"Matcher was not able to detect any matching styles for {styles} " + f"Matcher was not able to detect any matching styles for {kwargs['styles']} " "method.\nPlease ensure that variable fonts have fvar instances, " "both fonts have designspaces which overlap or ensure that both " "sets of static fonts have some matching styles." ) - + partitioned = partition(matcher.old_styles, MAX_STYLES) for p in partitioned: filter_styles = "|".join(style.name for style in p) - o = os.path.join(out, filter_styles.replace("|", "-")) + o = os.path.join(kwargs["out"], filter_styles.replace("|", "-")) if not os.path.exists(o): os.mkdir(o) - _ninja_diff( - fonts_before, - fonts_after, - diffbrowsers, - diffenator, - o, - imgs, - styles, - characters, - user_wordlist, - filter_styles, - pt_size, - threshold=threshold, - precision=precision, - no_words=no_words, - no_tables=no_tables, - ) - -def _ninja_diff( - fonts_before: list[DFont], - fonts_after: list[DFont], - diffbrowsers: bool = True, - diffenator: bool = True, - out: str = "out", - imgs: bool = False, - styles="instances", - characters=".*", - user_wordlist: str = "", - filter_styles: str = "", - pt_size: int = 20, - threshold: float = THRESHOLD, - precision: int = FONT_SIZE, - no_words: bool = False, - no_tables: bool = False, -): - w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - # Setup rules - w.comment("Rules") - w.newline() - w.comment("Build Hinting docs") - db_cmd = f'_diffbrowsers diff -fb $fonts_before -fa $fonts_after -s $styles -o $out -pt $pt_size -ch "$characters"' - if imgs: - db_cmd += " --imgs" - if filter_styles: - db_cmd += ' --filter-styles "$filters"' - if user_wordlist: - db_cmd += ' --user-wordlist "$user_wordlist"' - w.rule("diffbrowsers", db_cmd) - w.newline() + builder.out = o + builder.filter_styles = filter_styles + builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) - w.comment("Run diffenator VF") - diff_cmd = f'_diffenator $font_before $font_after --font-size $precision -t $threshold -o $out -ch "$characters"' - if user_wordlist: - diff_cmd += ' --user-wordlist "$user_wordlist"' - if no_words: - diff_cmd += ' --no-words' - if no_tables: - diff_cmd += ' --no-tables' - diff_inst_cmd = diff_cmd + " --coords $coords" - w.rule("diffenator", diff_cmd) - w.rule("diffenator-inst", diff_inst_cmd) - w.newline() - - # Setup build - w.comment("Build rules") - if diffbrowsers: - diffbrowsers_out = os.path.join(out, "diffbrowsers") - db_variables = dict( - fonts_before=[f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_before], - fonts_after=[f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_after], - styles=styles, - out=diffbrowsers_out, - pt_size=pt_size, - characters=characters, - ) - if filter_styles: - db_variables["filters"] = filter_styles - if user_wordlist: - db_variables["user_wordlist"] = user_wordlist - w.build(diffbrowsers_out, "diffbrowsers", variables=db_variables) - if diffenator: - matcher = FontMatcher(fonts_before, fonts_after) - getattr(matcher, styles)(filter_styles) - for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): - coords = new_style.coords - style = new_style.name.replace(" ", "-") - diff_variables: dict[str,str] = dict( - font_before=f'"{old_style.font.ttFont.reader.file.name}"', - font_after=f'"{new_style.font.ttFont.reader.file.name}"', - out=style, - threshold=str(threshold), - characters=characters, - precision=str(precision), - ) - if user_wordlist: - diff_variables["user_wordlist"] = user_wordlist - if coords: - diff_variables["coords"] = dict_coords_to_string(coords) - w.build( - os.path.join(out, style), - "diffenator-inst", - variables=diff_variables, - ) - else: - w.build( - os.path.join(out, style), "diffenator", variables=diff_variables - ) - w.close() - ninja._program("ninja", []) diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index 981f1a1..21f40d3 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -53,41 +53,13 @@ def main(**kwargs): diff_parser.add_argument("--no-words", action="store_true", help="Skip diffing wordlists") args = parser.parse_args() - if os.path.exists(NINJA_BUILD_FILE): - os.remove(NINJA_BUILD_FILE) - if os.path.exists(".ninja_log"): - os.remove(".ninja_log") if args.command == "proof": - fonts = [DFont(f) for f in args.fonts] - ninja_proof( - fonts, - out=args.out, - imgs=args.imgs, - styles=args.styles, - filter_styles=args.filter_styles, - characters=args.characters, - pt_size=args.pt_size, - user_wordlist=args.user_wordlist, - ) + args.fonts = [DFont(f) for f in args.fonts] + ninja_proof(**vars(args)) elif args.command == "diff": - fonts_before = [DFont(f) for f in args.fonts_before] - fonts_after = [DFont(f) for f in args.fonts_after] - ninja_diff( - fonts_before, - fonts_after, - out=args.out, - imgs=args.imgs, - styles=args.styles, - characters=args.characters, - diffenator=False if args.no_diffenator else True, - user_wordlist=args.user_wordlist, - filter_styles=args.filter_styles, - pt_size=args.pt_size, - threshold=args.threshold, - precision=args.precision, - no_words=args.no_words, - no_tables=args.no_tables, - ) + args.fonts_before = [DFont(f) for f in args.fonts_before] + args.fonts_after = [DFont(f) for f in args.fonts_after] + ninja_diff(**vars(args)) else: raise NotImplementedError(f"{args.command} not supported") # TODO (Marc F) find a better home for this when refactoring diff --git a/src/diffenator2/_diffbrowsers.py b/src/diffenator2/_diffbrowsers.py index c5ca133..bc7fa36 100755 --- a/src/diffenator2/_diffbrowsers.py +++ b/src/diffenator2/_diffbrowsers.py @@ -90,7 +90,8 @@ def main(): diff_parser.add_argument("--fonts-before", "-fb", nargs="+", required=True) diff_parser.add_argument("--fonts-after", "-fa", nargs="+", required=True) - args = parser.parse_args() + args, _ = parser.parse_known_args() + if args.command == "proof": fonts = [DFont(os.path.abspath(fp)) for fp in args.fonts] diff --git a/src/diffenator2/_diffenator.py b/src/diffenator2/_diffenator.py index da317a7..1633afd 100755 --- a/src/diffenator2/_diffenator.py +++ b/src/diffenator2/_diffenator.py @@ -105,7 +105,7 @@ def main(): parser.add_argument("--no-words", action="store_true") parser.add_argument("--no-tables", action="store_true") parser.add_argument("--out", "-o", default="out", help="Output html path") - args = parser.parse_args() + args, _ = parser.parse_known_args() coords = string_coords_to_dict(args.coords) if args.coords else None From 0c85a4a2e4777a22cb7109ef90d12088a404b267 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Mon, 30 Oct 2023 21:30:28 +0000 Subject: [PATCH 02/10] pass dicts around --- src/diffenator2/__init__.py | 115 +++++++++++++++---------------- src/diffenator2/__main__.py | 2 +- src/diffenator2/_diffbrowsers.py | 115 +++++++++---------------------- src/diffenator2/_diffenator.py | 50 ++++++++------ 4 files changed, 115 insertions(+), 167 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index e072599..ae6dc85 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -19,30 +19,25 @@ NINJA_BUILD_FILE = "build.ninja" + class NinjaBuilder: NINJA_LOG_FILE = ".ninja_log" NINJA_BUILD_FILE = "build.ninja" - def __init__(self, **kwargs): - for k, v in kwargs.items(): - setattr(self, k, v) + def __init__(self, cli_args): + self.cli_args = cli_args self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) def add_rule(self, name, string): cmd = self.populate_cli_command(string) - self.w.comment("Rules") self.w.newline() - self.w.rule(name, cmd) + self.w.rule(name, string) self.w.newline() - def build(self, out, name, varss): + def build_rules(self, out, name): # Setup build self.w.comment("Build rules") - variables = { - **{k: v for k, v in self.__dict__.items() if k not in ["command", "w"]}, - **varss, - } - self.w.build(out, name, variables=variables) + self.w.build(out, name, variables={"args": repr(self.cli_args)}) def run(self): self.w.close() @@ -50,57 +45,55 @@ def run(self): def proof_fonts(self, fonts): self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - self.add_rule("proofing", "_diffbrowsers proof $fonts") - varss = { - "fonts": [f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts] - } - self.build("proofing", varss) + self.add_rule("proofing", '_diffbrowsers "$args"') + self.build_rules(self.cli_args["out"], "proofing") self.run() - def diff_fonts(self, fonts_before, fonts_after): - self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - self.add_rule( - "diffbrowsers", "_diffbrowsers diff -fb $fonts_before -fa $fonts_after" - ) - varss = { - "fonts_before": [ - f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_before - ], - "fonts_after": [ - f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_after - ], - } - self.build(self.out, "diffbrowsers", varss) - - self.add_rule( - "diffenator", "_diffenator $font_before $font_after" - ) - - matcher = FontMatcher(fonts_before, fonts_after) - getattr(matcher, self.styles)(self.filter_styles) - for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): - coords = new_style.coords - style = new_style.name.replace(" ", "-") - diff_vars = { - "font_before": f'"{old_style.font.ttFont.reader.file.name}"', - "font_after": f'"{new_style.font.ttFont.reader.file.name}"', - } - # Fix this shit - self.fonts_before = None - self.fonts_after = None - o = os.path.join(self.out, style.replace(" ", "-")) - self.build(o, "diffenator", diff_vars) - self.run() +# def diff_fonts(self, fonts_before, fonts_after): +# self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) +# self.add_rule( +# "diffbrowsers", "_diffbrowsers diff -fb $fonts_before -fa $fonts_after" +# ) +# varss = { +# "fonts_before": [ +# f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_before +# ], +# "fonts_after": [ +# f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_after +# ], +# } +# self.build(self.out, "diffbrowsers", varss) +# +# self.add_rule( +# "diffenator", "_diffenator" +# ) +# +# matcher = FontMatcher(fonts_before, fonts_after) +# getattr(matcher, self.styles)(self.filter_styles) +# for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): +# coords = new_style.coords +# style = new_style.name.replace(" ", "-") +# diff_vars = { +# "font_before": f'"{old_style.font.ttFont.reader.file.name}"', +# "font_after": f'"{new_style.font.ttFont.reader.file.name}"', +# } +# # Fix this shit +# self.fonts_before = None +# self.fonts_after = None +# o = os.path.join(self.out, style.replace(" ", "-")) +# self.build_rules(o, "diffenator", diff_vars) +# self.run() def populate_cli_command(self, cmd): - for k, v in vars(self).items(): - k = k.replace("_", "-") - if any([not v, k == "w", k == "command"]): - continue - elif isinstance(v, bool): - cmd += f" --{k}" - elif isinstance(v, (str, int, float)): - cmd += f' --{k} "${k}"' + cmd += f" {repr(self.cli_args)}" +# for k, v in vars(self).items(): +# k = k.replace("_", "-") +# if any([not v, k == "w", k == "command"]): +# continue +# elif isinstance(v, bool): +# cmd += f" --{k}" +# elif isinstance(v, (str, int, float)): +# cmd += f' --{k} "${k}"' return cmd def __enter__(self): @@ -118,12 +111,13 @@ def ninja_proof(**kwargs): if not os.path.exists(kwargs["out"]): os.mkdir(kwargs["out"]) - with NinjaBuilder(**kwargs) as builder: + with NinjaBuilder(cli_args=kwargs) as builder: if kwargs["filter_styles"]: builder.proof_fonts(kwargs["fonts"]) return - font_styles = get_font_styles(kwargs["fonts"], kwargs["styles"]) + dfonts = [DFont(f) for f in kwargs["fonts"]] + font_styles = get_font_styles(dfonts, kwargs["styles"]) partitioned = partition(font_styles, MAX_STYLES) for font_styles in partitioned: filter_styles = "|".join(s.name for s in font_styles) @@ -163,4 +157,3 @@ def ninja_diff(**kwargs): builder.out = o builder.filter_styles = filter_styles builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) - diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index 21f40d3..0a52d18 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -27,6 +27,7 @@ def main(**kwargs): universal_options_parser.add_argument("--filter-styles", default=None) universal_options_parser.add_argument("--characters", "-ch", default=".*") universal_options_parser.add_argument("--pt-size", "-pt", default=20) + universal_options_parser.add_argument("--templates") universal_options_parser.add_argument( "--styles", "-s", choices=("instances", "cross_product", "masters"), default="instances", @@ -54,7 +55,6 @@ def main(**kwargs): args = parser.parse_args() if args.command == "proof": - args.fonts = [DFont(f) for f in args.fonts] ninja_proof(**vars(args)) elif args.command == "diff": args.fonts_before = [DFont(f) for f in args.fonts_before] diff --git a/src/diffenator2/_diffbrowsers.py b/src/diffenator2/_diffbrowsers.py index bc7fa36..844dd3f 100755 --- a/src/diffenator2/_diffbrowsers.py +++ b/src/diffenator2/_diffbrowsers.py @@ -30,68 +30,13 @@ from diffenator2.utils import re_filter_characters from glob import glob import os -import argparse +import sys +import ast +import types def main(): - parser = argparse.ArgumentParser() - subparsers = parser.add_subparsers( - dest="command", required=True, metavar='"proof" or "diff"' - ) - - # Optional args which can be used in all subparsers - universal_options_parser = argparse.ArgumentParser(add_help=False) - universal_options_parser.add_argument( - "--styles", "-s", choices=("instances", "cross_product", "masters"), - default="instances", - help="Show font instances, cross product or master styles" - ) - universal_options_parser.add_argument( - "--pt-size", "-pt", help="Change pt size of document text", default=14 - ) - universal_options_parser.add_argument( - "--out", "-o", help="Output dir", default="out" - ) - universal_options_parser.add_argument( - "--templates", - help="HTML templates. By default, diffenator/templates/diffbrowsers_*.html is used.", - default=glob( - os.path.join( - resource_filename("diffenator2", "templates"), "diffbrowsers*.html" - ) - ), - ) - universal_options_parser.add_argument( - "--imgs", action="store_true", help="Generate images using headless browsers" - ) - universal_options_parser.add_argument("--filter-styles", default=None) - universal_options_parser.add_argument("--characters", "-ch", default=".*") - universal_options_parser.add_argument( - "--user-wordlist", help="File of strings to visually compare", default=None - ) - - proof_parser = subparsers.add_parser( - "proof", - parents=[universal_options_parser], - help="Generate html proofing documents for a family", - ) - proof_parser.add_argument("fonts", nargs="+") - - diff_parser = subparsers.add_parser( - "diff", - parents=[universal_options_parser], - help="Generate html diff documents which compares two families. " - "Variable fonts can be compared against static fonts because we " - "match the fvar instances against the static fonts. To Match fonts " - "we use the font's name table records. For static fonts, the fullname " - "is used e.g 'Maven Pro Medium'. For variable fonts, the family name " - "+ fvar instance subfamilyname is used e.g 'Maven Pro' + 'Medium'.", - ) - diff_parser.add_argument("--fonts-before", "-fb", nargs="+", required=True) - diff_parser.add_argument("--fonts-after", "-fa", nargs="+", required=True) - - args, _ = parser.parse_known_args() - + args = types.SimpleNamespace(**ast.literal_eval(sys.argv[1])) if args.command == "proof": fonts = [DFont(os.path.abspath(fp)) for fp in args.fonts] @@ -100,35 +45,39 @@ def main(): characters = re_filter_characters(fonts[0], args.characters) proof_rendering( styles, - args.templates, - args.out, - filter_styles=args.filter_styles, - characters=characters, - pt_size=args.pt_size, - user_wordlist=args.user_wordlist, - ) - - elif args.command == "diff": - fonts_before = [DFont(os.path.abspath(fp), suffix="old") for fp in args.fonts_before] - fonts_after = [DFont(os.path.abspath(fp), suffix="new") for fp in args.fonts_after] - matcher = FontMatcher(fonts_before, fonts_after) - getattr(matcher, args.styles)(args.filter_styles) - characters = re_filter_characters(fonts_before[0], args.characters) - diff_rendering( - matcher, - args.templates, + glob( + os.path.join( + resource_filename("diffenator2", "templates"), "diffbrowsers*.html" + ) + ), args.out, filter_styles=args.filter_styles, characters=characters, pt_size=args.pt_size, user_wordlist=args.user_wordlist, ) - - if args.imgs: - imgs_out = os.path.join(args.out, "imgs") - from diffenator2.screenshot import screenshot_dir - screenshot_dir(args.out, imgs_out) - - +# +# elif args.command == "diff": +# fonts_before = [DFont(os.path.abspath(fp), suffix="old") for fp in args.fonts_before] +# fonts_after = [DFont(os.path.abspath(fp), suffix="new") for fp in args.fonts_after] +# matcher = FontMatcher(fonts_before, fonts_after) +# getattr(matcher, args.styles)(args.filter_styles) +# characters = re_filter_characters(fonts_before[0], args.characters) +# diff_rendering( +# matcher, +# args.templates, +# args.out, +# filter_styles=args.filter_styles, +# characters=characters, +# pt_size=args.pt_size, +# user_wordlist=args.user_wordlist, +# ) +# +# if args.imgs: +# imgs_out = os.path.join(args.out, "imgs") +# from diffenator2.screenshot import screenshot_dir +# screenshot_dir(args.out, imgs_out) +# +# if __name__ == "__main__": main() diff --git a/src/diffenator2/_diffenator.py b/src/diffenator2/_diffenator.py index 1633afd..c1065b3 100755 --- a/src/diffenator2/_diffenator.py +++ b/src/diffenator2/_diffenator.py @@ -86,28 +86,34 @@ def to_html(self, templates, out): def main(): - parser = argparse.ArgumentParser() - parser.add_argument("old_font") - parser.add_argument("new_font") - parser.add_argument( - "--template", - default=resource_filename( - "diffenator2", os.path.join("templates", "diffenator.html") - ), - ) - parser.add_argument( - "--user-wordlist", help="File of strings to visually compare", default=None - ) - parser.add_argument("--coords", "-c", default={}) - parser.add_argument("--threshold", "-t", default=THRESHOLD, type=float) - parser.add_argument("--font-size", "-pt", default=FONT_SIZE, type=int) - parser.add_argument("--characters", "-ch", default=".*") - parser.add_argument("--no-words", action="store_true") - parser.add_argument("--no-tables", action="store_true") - parser.add_argument("--out", "-o", default="out", help="Output html path") - args, _ = parser.parse_known_args() - - coords = string_coords_to_dict(args.coords) if args.coords else None +# parser = argparse.ArgumentParser() +# parser.add_argument("old_font") +# parser.add_argument("new_font") +# parser.add_argument( +# "--template", +# default=resource_filename( +# "diffenator2", os.path.join("templates", "diffenator.html") +# ), +# ) +# parser.add_argument( +# "--user-wordlist", help="File of strings to visually compare", default=None +# ) +# parser.add_argument("--coords", "-c", default={}) +# parser.add_argument("--threshold", "-t", default=THRESHOLD, type=float) +# parser.add_argument("--font-size", "-pt", default=FONT_SIZE, type=int) +# parser.add_argument("--characters", "-ch", default=".*") +# parser.add_argument("--no-words", action="store_true") +# parser.add_argument("--no-tables", action="store_true") +# parser.add_argument("--out", "-o", default="out", help="Output html path") +# args, _ = parser.parse_known_args() + + from types import SimpleNamespace + import fire + args = SimpleNamespace(**fire.Fire(lambda obj: obj)) + import pdb + pdb.set_trace() + + coords = None if not args.coords else string_coords_to_dict(args.coords) old_font = DFont(os.path.abspath(args.old_font), suffix="old") new_font = DFont(os.path.abspath(args.new_font), suffix="new") From af5fc8b140f0096452e2db84328c29bc156d3291 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Mon, 30 Oct 2023 21:34:32 +0000 Subject: [PATCH 03/10] simp --- src/diffenator2/__init__.py | 16 +++------------- 1 file changed, 3 insertions(+), 13 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index ae6dc85..13cb0ad 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -28,25 +28,15 @@ def __init__(self, cli_args): self.cli_args = cli_args self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - def add_rule(self, name, string): - cmd = self.populate_cli_command(string) - self.w.newline() - self.w.rule(name, string) - self.w.newline() - - def build_rules(self, out, name): - # Setup build - self.w.comment("Build rules") - self.w.build(out, name, variables={"args": repr(self.cli_args)}) - def run(self): self.w.close() ninja._program("ninja", []) def proof_fonts(self, fonts): self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - self.add_rule("proofing", '_diffbrowsers "$args"') - self.build_rules(self.cli_args["out"], "proofing") + self.w.rule("proofing", '_diffbrowsers "$args"') + self.w.newline() + self.w.build(self.cli_args["out"], "proofing", variables={"args": repr(self.cli_args)}) self.run() # def diff_fonts(self, fonts_before, fonts_after): From e018bae74a629795d799d130908d25b489ed5447 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Tue, 31 Oct 2023 08:45:18 +0000 Subject: [PATCH 04/10] simplify --- src/diffenator2/__init__.py | 27 +++++++-------------------- src/diffenator2/__main__.py | 2 -- 2 files changed, 7 insertions(+), 22 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index 13cb0ad..bb8a8a8 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -19,7 +19,6 @@ NINJA_BUILD_FILE = "build.ninja" - class NinjaBuilder: NINJA_LOG_FILE = ".ninja_log" NINJA_BUILD_FILE = "build.ninja" @@ -32,7 +31,7 @@ def run(self): self.w.close() ninja._program("ninja", []) - def proof_fonts(self, fonts): + def proof_fonts(self): self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) self.w.rule("proofing", '_diffbrowsers "$args"') self.w.newline() @@ -74,18 +73,6 @@ def proof_fonts(self, fonts): # self.build_rules(o, "diffenator", diff_vars) # self.run() - def populate_cli_command(self, cmd): - cmd += f" {repr(self.cli_args)}" -# for k, v in vars(self).items(): -# k = k.replace("_", "-") -# if any([not v, k == "w", k == "command"]): -# continue -# elif isinstance(v, bool): -# cmd += f" --{k}" -# elif isinstance(v, (str, int, float)): -# cmd += f' --{k} "${k}"' - return cmd - def __enter__(self): return self @@ -103,21 +90,21 @@ def ninja_proof(**kwargs): with NinjaBuilder(cli_args=kwargs) as builder: if kwargs["filter_styles"]: - builder.proof_fonts(kwargs["fonts"]) + builder.proof_fonts() return dfonts = [DFont(f) for f in kwargs["fonts"]] font_styles = get_font_styles(dfonts, kwargs["styles"]) partitioned = partition(font_styles, MAX_STYLES) + out = kwargs["out"] for font_styles in partitioned: filter_styles = "|".join(s.name for s in font_styles) - o = os.path.join(kwargs["out"], filter_styles.replace("|", "-")) + o = os.path.join(out, filter_styles.replace("|", "-")) if not os.path.exists(o): os.mkdir(o) - builder.out = o - builder.filter_styles = filter_styles - builder.proof_fonts(kwargs["fonts"]) - + builder.cli_args["out"] = o + builder.cli_args["filter_styles"] = filter_styles + builder.proof_fonts() def ninja_diff(**kwargs): if not os.path.exists(kwargs["out"]): diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index 0a52d18..1043d0f 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -8,7 +8,6 @@ from diffenator2.renderer import FONT_SIZE - def main(**kwargs): if kwargs: args = Namespace(**kwargs) @@ -27,7 +26,6 @@ def main(**kwargs): universal_options_parser.add_argument("--filter-styles", default=None) universal_options_parser.add_argument("--characters", "-ch", default=".*") universal_options_parser.add_argument("--pt-size", "-pt", default=20) - universal_options_parser.add_argument("--templates") universal_options_parser.add_argument( "--styles", "-s", choices=("instances", "cross_product", "masters"), default="instances", From 9b8a3b8841db037d3f11bd59e0375f50ba223d7f Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Tue, 31 Oct 2023 09:16:15 +0000 Subject: [PATCH 05/10] wip diffbrowsers --- src/diffenator2/__init__.py | 32 +++++++++++--------------- src/diffenator2/__main__.py | 2 -- src/diffenator2/_diffbrowsers.py | 39 +++++++++++++++++++------------- 3 files changed, 36 insertions(+), 37 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index bb8a8a8..50286a5 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -38,20 +38,11 @@ def proof_fonts(self): self.w.build(self.cli_args["out"], "proofing", variables={"args": repr(self.cli_args)}) self.run() -# def diff_fonts(self, fonts_before, fonts_after): -# self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) -# self.add_rule( -# "diffbrowsers", "_diffbrowsers diff -fb $fonts_before -fa $fonts_after" -# ) -# varss = { -# "fonts_before": [ -# f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_before -# ], -# "fonts_after": [ -# f'"{os.path.abspath(f.ttFont.reader.file.name)}"' for f in fonts_after -# ], -# } -# self.build(self.out, "diffbrowsers", varss) + def diff_fonts(self, fonts_before, fonts_after): + self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) + self.w.rule("diffbrowsers", '_diffbrowsers "$args"') + self.w.build(self.cli_args["out"], "diffbrowsers", variables={"args": repr(self.cli_args)}) + self.run() # # self.add_rule( # "diffenator", "_diffenator" @@ -110,12 +101,14 @@ def ninja_diff(**kwargs): if not os.path.exists(kwargs["out"]): os.mkdir(kwargs["out"]) - with NinjaBuilder(**kwargs) as builder: + with NinjaBuilder(cli_args=kwargs) as builder: if kwargs["filter_styles"]: builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) return - matcher = FontMatcher(kwargs["fonts_before"], kwargs["fonts_after"]) + fonts_before = [DFont(f) for f in kwargs["fonts_before"]] + fonts_after = [DFont(f) for f in kwargs["fonts_after"]] + matcher = FontMatcher(fonts_before, fonts_after) getattr(matcher, kwargs["styles"])() if not matcher.old_styles and not matcher.new_styles: raise ValueError( @@ -126,11 +119,12 @@ def ninja_diff(**kwargs): ) partitioned = partition(matcher.old_styles, MAX_STYLES) + out = kwargs["out"] for p in partitioned: filter_styles = "|".join(style.name for style in p) - o = os.path.join(kwargs["out"], filter_styles.replace("|", "-")) + o = os.path.join(out, filter_styles.replace("|", "-")) if not os.path.exists(o): os.mkdir(o) - builder.out = o - builder.filter_styles = filter_styles + builder.cli_args["out"] = o + builder.cli_args["filter_styles"] = filter_styles builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index 1043d0f..600d5b9 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -55,8 +55,6 @@ def main(**kwargs): if args.command == "proof": ninja_proof(**vars(args)) elif args.command == "diff": - args.fonts_before = [DFont(f) for f in args.fonts_before] - args.fonts_after = [DFont(f) for f in args.fonts_after] ninja_diff(**vars(args)) else: raise NotImplementedError(f"{args.command} not supported") diff --git a/src/diffenator2/_diffbrowsers.py b/src/diffenator2/_diffbrowsers.py index 844dd3f..8cc6882 100755 --- a/src/diffenator2/_diffbrowsers.py +++ b/src/diffenator2/_diffbrowsers.py @@ -36,6 +36,7 @@ def main(): + # Maybe json load/dump is better args = types.SimpleNamespace(**ast.literal_eval(sys.argv[1])) if args.command == "proof": @@ -45,6 +46,28 @@ def main(): characters = re_filter_characters(fonts[0], args.characters) proof_rendering( styles, + # chuck this into __main__ + glob( + os.path.join( + resource_filename("diffenator2", "templates"), "diffbrowsers*.html" + ) + ), + args.out, + filter_styles=args.filter_styles, + characters=characters, + pt_size=args.pt_size, + user_wordlist=args.user_wordlist, + ) + + elif args.command == "diff": + fonts_before = [DFont(os.path.abspath(fp), suffix="old") for fp in args.fonts_before] + fonts_after = [DFont(os.path.abspath(fp), suffix="new") for fp in args.fonts_after] + matcher = FontMatcher(fonts_before, fonts_after) + getattr(matcher, args.styles)(args.filter_styles) + characters = re_filter_characters(fonts_before[0], args.characters) + diff_rendering( + matcher, + # chuck this into __main__ glob( os.path.join( resource_filename("diffenator2", "templates"), "diffbrowsers*.html" @@ -56,22 +79,6 @@ def main(): pt_size=args.pt_size, user_wordlist=args.user_wordlist, ) -# -# elif args.command == "diff": -# fonts_before = [DFont(os.path.abspath(fp), suffix="old") for fp in args.fonts_before] -# fonts_after = [DFont(os.path.abspath(fp), suffix="new") for fp in args.fonts_after] -# matcher = FontMatcher(fonts_before, fonts_after) -# getattr(matcher, args.styles)(args.filter_styles) -# characters = re_filter_characters(fonts_before[0], args.characters) -# diff_rendering( -# matcher, -# args.templates, -# args.out, -# filter_styles=args.filter_styles, -# characters=characters, -# pt_size=args.pt_size, -# user_wordlist=args.user_wordlist, -# ) # # if args.imgs: # imgs_out = os.path.join(args.out, "imgs") From 84fa4a035263c0658eddd8ccfe5248600d25f9ab Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Tue, 31 Oct 2023 10:53:25 +0000 Subject: [PATCH 06/10] working --- src/diffenator2/__init__.py | 46 ++++++++++++++++------------------ src/diffenator2/__main__.py | 9 +++++++ src/diffenator2/_diffenator.py | 36 ++++++-------------------- 3 files changed, 38 insertions(+), 53 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index 50286a5..5eeeaa4 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -42,27 +42,25 @@ def diff_fonts(self, fonts_before, fonts_after): self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) self.w.rule("diffbrowsers", '_diffbrowsers "$args"') self.w.build(self.cli_args["out"], "diffbrowsers", variables={"args": repr(self.cli_args)}) + self.w.newline() + + self.w.rule("diffenator", '_diffenator "$args"') + matcher = FontMatcher(fonts_before, fonts_after) + + getattr(matcher, self.cli_args["styles"])(self.cli_args["filter_styles"]) + for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): + coords = new_style.coords + style = new_style.name.replace(" ", "-") + o = os.path.join(self.cli_args["out"], style.replace(" ", "-")) + self.w.build(o, "diffenator", variables={"args": repr( + {**self.cli_args, **{ + "coords": dict_coords_to_string(coords), + "old_font": old_style.font.ttFont.reader.file.name, + "new_font": new_style.font.ttFont.reader.file.name, + "out": o, + }} + )}) self.run() -# -# self.add_rule( -# "diffenator", "_diffenator" -# ) -# -# matcher = FontMatcher(fonts_before, fonts_after) -# getattr(matcher, self.styles)(self.filter_styles) -# for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): -# coords = new_style.coords -# style = new_style.name.replace(" ", "-") -# diff_vars = { -# "font_before": f'"{old_style.font.ttFont.reader.file.name}"', -# "font_after": f'"{new_style.font.ttFont.reader.file.name}"', -# } -# # Fix this shit -# self.fonts_before = None -# self.fonts_after = None -# o = os.path.join(self.out, style.replace(" ", "-")) -# self.build_rules(o, "diffenator", diff_vars) -# self.run() def __enter__(self): return self @@ -101,13 +99,13 @@ def ninja_diff(**kwargs): if not os.path.exists(kwargs["out"]): os.mkdir(kwargs["out"]) + fonts_before = [DFont(f) for f in kwargs["fonts_before"]] + fonts_after = [DFont(f) for f in kwargs["fonts_after"]] with NinjaBuilder(cli_args=kwargs) as builder: if kwargs["filter_styles"]: - builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) + builder.diff_fonts(fonts_before, fonts_after) return - fonts_before = [DFont(f) for f in kwargs["fonts_before"]] - fonts_after = [DFont(f) for f in kwargs["fonts_after"]] matcher = FontMatcher(fonts_before, fonts_after) getattr(matcher, kwargs["styles"])() if not matcher.old_styles and not matcher.new_styles: @@ -127,4 +125,4 @@ def ninja_diff(**kwargs): os.mkdir(o) builder.cli_args["out"] = o builder.cli_args["filter_styles"] = filter_styles - builder.diff_fonts(kwargs["fonts_before"], kwargs["fonts_after"]) + builder.diff_fonts(fonts_before, fonts_after) diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index 600d5b9..fa61deb 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -6,6 +6,7 @@ from diffenator2.font import DFont from diffenator2.html import build_index_page from diffenator2.renderer import FONT_SIZE +from pkg_resources import resource_filename def main(**kwargs): @@ -48,8 +49,16 @@ def main(**kwargs): diff_parser.add_argument("--no-diffenator", default=False, action="store_true") diff_parser.add_argument("--threshold", "-t", type=float, default=THRESHOLD) diff_parser.add_argument("--precision", default=FONT_SIZE) + # TODO this can just be precision + diff_parser.add_argument("--font-size", default=FONT_SIZE) diff_parser.add_argument("--no-tables", action="store_true", help="Skip diffing font tables") diff_parser.add_argument("--no-words", action="store_true", help="Skip diffing wordlists") + parser.add_argument( + "--template", + default=resource_filename( + "diffenator2", os.path.join("templates", "diffenator.html") + ), + ) args = parser.parse_args() if args.command == "proof": diff --git a/src/diffenator2/_diffenator.py b/src/diffenator2/_diffenator.py index c1065b3..5ec5c9f 100755 --- a/src/diffenator2/_diffenator.py +++ b/src/diffenator2/_diffenator.py @@ -13,10 +13,12 @@ from diffenator2.matcher import FontMatcher from pkg_resources import resource_filename import os -import argparse from diffenator2.shape import test_words, test_fonts from diffenator2 import jfont, THRESHOLD from diffenator2.html import diffenator_report +import types +import ast +import sys class DiffFonts: @@ -86,34 +88,10 @@ def to_html(self, templates, out): def main(): -# parser = argparse.ArgumentParser() -# parser.add_argument("old_font") -# parser.add_argument("new_font") -# parser.add_argument( -# "--template", -# default=resource_filename( -# "diffenator2", os.path.join("templates", "diffenator.html") -# ), -# ) -# parser.add_argument( -# "--user-wordlist", help="File of strings to visually compare", default=None -# ) -# parser.add_argument("--coords", "-c", default={}) -# parser.add_argument("--threshold", "-t", default=THRESHOLD, type=float) -# parser.add_argument("--font-size", "-pt", default=FONT_SIZE, type=int) -# parser.add_argument("--characters", "-ch", default=".*") -# parser.add_argument("--no-words", action="store_true") -# parser.add_argument("--no-tables", action="store_true") -# parser.add_argument("--out", "-o", default="out", help="Output html path") -# args, _ = parser.parse_known_args() - - from types import SimpleNamespace - import fire - args = SimpleNamespace(**fire.Fire(lambda obj: obj)) - import pdb - pdb.set_trace() - - coords = None if not args.coords else string_coords_to_dict(args.coords) + # Maybe json load/dump is better + args = types.SimpleNamespace(**ast.literal_eval(sys.argv[1])) + + coords = string_coords_to_dict(args.coords) old_font = DFont(os.path.abspath(args.old_font), suffix="old") new_font = DFont(os.path.abspath(args.new_font), suffix="new") From 0e2f0d9ee3675cc3b416d26266595369587a3ad9 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Tue, 31 Oct 2023 13:21:16 +0000 Subject: [PATCH 07/10] readd imgs --- src/diffenator2/_diffbrowsers.py | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/diffenator2/_diffbrowsers.py b/src/diffenator2/_diffbrowsers.py index 8cc6882..1490012 100755 --- a/src/diffenator2/_diffbrowsers.py +++ b/src/diffenator2/_diffbrowsers.py @@ -79,12 +79,12 @@ def main(): pt_size=args.pt_size, user_wordlist=args.user_wordlist, ) -# -# if args.imgs: -# imgs_out = os.path.join(args.out, "imgs") -# from diffenator2.screenshot import screenshot_dir -# screenshot_dir(args.out, imgs_out) -# -# + + if args.imgs: + imgs_out = os.path.join(args.out, "imgs") + from diffenator2.screenshot import screenshot_dir + screenshot_dir(args.out, imgs_out) + + if __name__ == "__main__": main() From 8261465cf475edc5cef38c2e9f0d1b85e143f20e Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Tue, 31 Oct 2023 13:21:25 +0000 Subject: [PATCH 08/10] refactor tests --- tests/test_functional.py | 36 +++++++-------- tests/test_ninja.py | 94 ---------------------------------------- 2 files changed, 19 insertions(+), 111 deletions(-) delete mode 100644 tests/test_ninja.py diff --git a/tests/test_functional.py b/tests/test_functional.py index 2c42f71..960dab9 100644 --- a/tests/test_functional.py +++ b/tests/test_functional.py @@ -7,12 +7,13 @@ + @pytest.mark.parametrize( "fp, cmd", [ - (mavenpro_vf, ["_diffbrowsers", "proof", mavenpro_vf]), - (mavenpro_vf, ["_diffbrowsers", "proof", mavenpro_vf, "--imgs"]), - (mavenpro_vf, ["_diffbrowsers", "proof", mavenpro_vf, "--filter-styles=Medium|ExtraBold"]), + (mavenpro_vf, ["diffenator2", "proof", mavenpro_vf, "--filter-styles", "Regular"]), + (mavenpro_vf, ["diffenator2", "proof", mavenpro_vf, "--filter-styles", "Regular", "--imgs"]), + (mavenpro_vf, ["diffenator2", "proof", mavenpro_vf, "--filter-styles=Medium|ExtraBold"]), ] ) def test_run_diffbrowsers_proof(fp, cmd): @@ -32,7 +33,7 @@ def test_run_diffbrowsers_proof(fp, cmd): ) def test_run_diffbrowsers_proof_imgs(fp): with tempfile.TemporaryDirectory() as tmp_dir: - subprocess.run(["_diffbrowsers", "proof", fp, "--imgs", "-o", tmp_dir], check=True) + subprocess.run(["diffenator2", "proof", fp, "--imgs", "-o", tmp_dir, "--filter-styles", ".*"], check=True) imgs, html = [], [] # check images have been generated and there's an image for every html page @@ -44,8 +45,8 @@ def test_run_diffbrowsers_proof_imgs(fp): html.append(f) else: imgs.append(f) - # There should at least be an image for each html page apart from the proofing page - assert len(imgs) >= len(html)-1 + # There should be images for the text, glyphs and waterfall page + assert len(imgs) == 3 @@ -61,7 +62,7 @@ def test_run_diffbrowsers_proof_imgs(fp): ) def test_diffenator(fp_before, fp_after): with tempfile.TemporaryDirectory() as tmp_dir: - subprocess.run(["_diffenator", fp_before, fp_after, "-o", tmp_dir]) + subprocess.run(["diffenator2", "diff", "-fb", fp_before, "-fa", fp_after, "-o", tmp_dir, "--filter-styles", ".*"]) new_font = f"old-{os.path.basename(fp_before)}" old_font = f"new-{os.path.basename(fp_after)}" assert new_font in os.listdir(tmp_dir) @@ -80,8 +81,9 @@ def test_diffenator(fp_before, fp_after): ) def test_diffenator_threshold(fp_before, fp_after, threshold, has, missing): with tempfile.TemporaryDirectory() as tmp_dir: - subprocess.run(["_diffenator", fp_before, fp_after, "-o", tmp_dir, "-t", str(threshold)]) - with open(os.path.join(tmp_dir, "diffenator.html"), "r", encoding="utf8") as doc: + subprocess.run( + ["diffenator2", "diff", "-fb", fp_before, "-fa", fp_after, "-o", tmp_dir, "-t", str(threshold), "--filter-styles", "Regular"]) + with open(os.path.join(tmp_dir, "Regular", "diffenator.html"), "r", encoding="utf8") as doc: report = doc.read() for string in has: assert string in report @@ -93,18 +95,18 @@ def test_diffenator_threshold(fp_before, fp_after, threshold, has, missing): @pytest.mark.parametrize( "fp, cmd, pattern, has, missing", [ - (mavenpro_vf, "proof", ".*", ['style="font-size: 14pt">an tan'], []), - (mavenpro_vf, "proof", "[an]{1,2}", ['style="font-size: 14pt">an'], []), - (mavenpro_vf, "diff", ".*", ['style="font-size: 14pt">an tan'], []), - (mavenpro_vf, "diff", "[an]{1,2}", ['style="font-size: 14pt">an'], []), + (mavenpro_vf, "proof", ".*", ['>an tan'], []), + (mavenpro_vf, "proof", "[an]{1,2}", ['>an'], []), + (mavenpro_vf, "diff", ".*", ['>an tan'], []), + (mavenpro_vf, "diff", "[an]{1,2}", ['>an'], []), ] ) def test_diffbrowsers_filter_characters(fp, cmd, pattern, has, missing): with tempfile.TemporaryDirectory() as tmp_dir: if cmd == "proof": - subprocess.run(["_diffbrowsers", cmd, fp, "-c", pattern, "-o", tmp_dir]) + subprocess.run(["diffenator2", cmd, fp, "-c", pattern, "-o", tmp_dir, "--filter-styles", "Regular"]) elif cmd == "diff": - subprocess.run(["_diffbrowsers", cmd, "-fb", fp, "-fa", fp, "-c", pattern, "-o", tmp_dir]) + subprocess.run(["diffenator2", cmd, "-fb", fp, "-fa", fp, "-c", pattern, "-o", tmp_dir, "--filter-styles", "Regular"]) with open(os.path.join(tmp_dir, "diffbrowsers_text.html"), "r", encoding="utf8") as doc: report = doc.read() @@ -124,8 +126,8 @@ def test_diffbrowsers_filter_characters(fp, cmd, pattern, has, missing): ) def test_diffenator_filter_characters(fp_before, fp_after, pattern, has, missing): with tempfile.TemporaryDirectory() as tmp_dir: - subprocess.run(["_diffenator", fp_before, fp_after, "-o", tmp_dir, "-ch", pattern]) - with open(os.path.join(tmp_dir, "diffenator.html"), "r", encoding="utf8") as doc: + subprocess.run(["diffenator2", "diff", "-fb", fp_before, "-fa", fp_after, "-o", tmp_dir, "-ch", pattern, "--filter-styles", "Regular"]) + with open(os.path.join(tmp_dir, "Regular", "diffenator.html"), "r", encoding="utf8") as doc: report = doc.read() for string in has: assert string in report diff --git a/tests/test_ninja.py b/tests/test_ninja.py deleted file mode 100644 index e5ca451..0000000 --- a/tests/test_ninja.py +++ /dev/null @@ -1,94 +0,0 @@ -from . import * -import pytest -from diffenator2.font import DFont -import re - - -def assert_match(expected_fp): - with open(expected_fp) as expected, open("build.ninja") as current: - for ix, (exp, cur) in enumerate(zip(expected.readlines(), current.readlines())): - assert re.search(exp, cur), "Expected: %sFound %s at line %i of %s" % (exp, cur, ix, expected_fp) - - -@pytest.mark.parametrize( - """kwargs,expected_fp""", - [ - # standard, just two fonts families - ( - dict( - fonts_before=[DFont(mavenpro_vf)], - fonts_after=[DFont(mavenpro_vf_mod)], - ), - os.path.join(DATA_FP, "ninja_files", "diff-standard.txt") - ), - # include imgs - ( - dict( - fonts_before=[DFont(mavenpro_vf)], - fonts_after=[DFont(mavenpro_vf_mod)], - imgs=True, - ), - os.path.join(DATA_FP, "ninja_files", "diff-imgs.txt") - ), - # include filter-styles - ( - dict( - fonts_before=[DFont(mavenpro_vf)], - fonts_after=[DFont(mavenpro_vf_mod)], - imgs=True, - filter_styles="Medium|ExtraBold" - ), - os.path.join(DATA_FP, "ninja_files", "diff-filter-styles.txt") - ), - # change threshold - ( - dict( - fonts_before=[DFont(mavenpro_vf)], - fonts_after=[DFont(mavenpro_vf_mod)], - threshold=0.01, - ), - os.path.join(DATA_FP, "ninja_files", "diff-threshold.txt") - ), - ] -) -def test_run_ninja_diff(kwargs, expected_fp): - from diffenator2 import _ninja_diff - - _ninja_diff(**kwargs) - assert_match(expected_fp) - - -@pytest.mark.parametrize( - """kwargs,expected_fp""", - [ - # standard - ( - dict( - fonts=[DFont(mavenpro_vf)], - ), - os.path.join(DATA_FP, "ninja_files", "proof-standard.txt") - ), - # imgs - ( - dict( - fonts=[DFont(mavenpro_vf)], - imgs=True, - ), - os.path.join(DATA_FP, "ninja_files", "proof-imgs.txt") - ), - # include filter_styles - ( - dict( - fonts=[DFont(mavenpro_vf)], - imgs=True, - filter_styles="Medium|Bold" - ), - os.path.join(DATA_FP, "ninja_files", "proof-filter-styles.txt") - ), - ] -) -def test_run_ninja_proof(kwargs, expected_fp): - from diffenator2 import _ninja_proof - - _ninja_proof(**kwargs) - assert_match(expected_fp) From c545f2364079e7db2667c19a8ac7a5da5d2b53d5 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Wed, 1 Nov 2023 12:57:00 +0000 Subject: [PATCH 09/10] reinclude args for ninja funcs --- src/diffenator2/__init__.py | 72 +++++++++++++++++++++++++++---------- 1 file changed, 53 insertions(+), 19 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index 5eeeaa4..22167a1 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -7,6 +7,7 @@ from diffenator2.font import DFont, get_font_styles from diffenator2.utils import partition from diffenator2.matcher import FontMatcher +from pkg_resources import resource_filename import shutil import ninja @@ -73,19 +74,29 @@ def __exit__(self, exc_type, exc_val, exc_tb): os.remove(self.NINJA_LOG_FILE) -def ninja_proof(**kwargs): - if not os.path.exists(kwargs["out"]): - os.mkdir(kwargs["out"]) - - with NinjaBuilder(cli_args=kwargs) as builder: - if kwargs["filter_styles"]: +def ninja_proof( + fonts, + out: str = "out", + styles="instances", + filter_styles: str = "", + characters: str = ".*", + pt_size: int = 20, + command="proof", + user_wordlist: str = "", + **kwargs +): + if not os.path.exists(out): + os.mkdir(out) + + args = {**locals(), **locals().pop("kwargs")} + with NinjaBuilder(cli_args=args) as builder: + if filter_styles: builder.proof_fonts() return - dfonts = [DFont(f) for f in kwargs["fonts"]] - font_styles = get_font_styles(dfonts, kwargs["styles"]) + dfonts = [DFont(f) for f in fonts] + font_styles = get_font_styles(dfonts, styles) partitioned = partition(font_styles, MAX_STYLES) - out = kwargs["out"] for font_styles in partitioned: filter_styles = "|".join(s.name for s in font_styles) o = os.path.join(out, filter_styles.replace("|", "-")) @@ -95,29 +106,52 @@ def ninja_proof(**kwargs): builder.cli_args["filter_styles"] = filter_styles builder.proof_fonts() -def ninja_diff(**kwargs): - if not os.path.exists(kwargs["out"]): - os.mkdir(kwargs["out"]) - fonts_before = [DFont(f) for f in kwargs["fonts_before"]] - fonts_after = [DFont(f) for f in kwargs["fonts_after"]] - with NinjaBuilder(cli_args=kwargs) as builder: - if kwargs["filter_styles"]: +def ninja_diff( + fonts_before: list[DFont], + fonts_after: list[DFont], + diffbrowsers: bool = True, + diffenator: bool = True, + out: str = "out", + imgs: bool = False, + styles: str = "instances", + characters: str = ".*", + user_wordlist: str = "", + filter_styles: str = "", + font_size: int = 20, + pt_size: int = 20, + threshold: float = THRESHOLD, + precision: int = FONT_SIZE, + no_words: bool = False, + no_tables: bool = False, + template = resource_filename( + "diffenator2", os.path.join("templates", "diffenator.html") + ), + command="diff", + **kwargs +): + args = {**locals(), **locals().pop("kwargs")} + if not os.path.exists(out): + os.mkdir(out) + + fonts_before = [DFont(f) for f in fonts_before] + fonts_after = [DFont(f) for f in fonts_after] + with NinjaBuilder(cli_args=args) as builder: + if filter_styles: builder.diff_fonts(fonts_before, fonts_after) return matcher = FontMatcher(fonts_before, fonts_after) - getattr(matcher, kwargs["styles"])() + getattr(matcher, styles)() if not matcher.old_styles and not matcher.new_styles: raise ValueError( - f"Matcher was not able to detect any matching styles for {kwargs['styles']} " + f"Matcher was not able to detect any matching styles for {styles} " "method.\nPlease ensure that variable fonts have fvar instances, " "both fonts have designspaces which overlap or ensure that both " "sets of static fonts have some matching styles." ) partitioned = partition(matcher.old_styles, MAX_STYLES) - out = kwargs["out"] for p in partitioned: filter_styles = "|".join(style.name for style in p) o = os.path.join(out, filter_styles.replace("|", "-")) From fb230646fb4b82ab07b9e5f26a01c784cdc12fd1 Mon Sep 17 00:00:00 2001 From: Marc Foley Date: Wed, 1 Nov 2023 13:27:35 +0000 Subject: [PATCH 10/10] make diffbrowsers and diffenator optional --- src/diffenator2/__init__.py | 40 ++++++++++++++++++---------------- src/diffenator2/__main__.py | 2 +- src/diffenator2/_diffenator.py | 2 +- 3 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/diffenator2/__init__.py b/src/diffenator2/__init__.py index 22167a1..a68d066 100644 --- a/src/diffenator2/__init__.py +++ b/src/diffenator2/__init__.py @@ -41,26 +41,28 @@ def proof_fonts(self): def diff_fonts(self, fonts_before, fonts_after): self.w = Writer(open(NINJA_BUILD_FILE, "w", encoding="utf8")) - self.w.rule("diffbrowsers", '_diffbrowsers "$args"') - self.w.build(self.cli_args["out"], "diffbrowsers", variables={"args": repr(self.cli_args)}) + if self.cli_args["diffbrowsers"]: + self.w.rule("diffbrowsers", '_diffbrowsers "$args"') + self.w.build(self.cli_args["out"], "diffbrowsers", variables={"args": repr(self.cli_args)}) self.w.newline() - self.w.rule("diffenator", '_diffenator "$args"') - matcher = FontMatcher(fonts_before, fonts_after) - - getattr(matcher, self.cli_args["styles"])(self.cli_args["filter_styles"]) - for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): - coords = new_style.coords - style = new_style.name.replace(" ", "-") - o = os.path.join(self.cli_args["out"], style.replace(" ", "-")) - self.w.build(o, "diffenator", variables={"args": repr( - {**self.cli_args, **{ - "coords": dict_coords_to_string(coords), - "old_font": old_style.font.ttFont.reader.file.name, - "new_font": new_style.font.ttFont.reader.file.name, - "out": o, - }} - )}) + if self.cli_args["diffenator"]: + self.w.rule("diffenator", '_diffenator "$args"') + matcher = FontMatcher(fonts_before, fonts_after) + + getattr(matcher, self.cli_args["styles"])(self.cli_args["filter_styles"]) + for old_style, new_style in zip(matcher.old_styles, matcher.new_styles): + coords = new_style.coords + style = new_style.name.replace(" ", "-") + o = os.path.join(self.cli_args["out"], style.replace(" ", "-")) + self.w.build(o, "diffenator", variables={"args": repr( + {**self.cli_args, **{ + "coords": dict_coords_to_string(coords), + "old_font": old_style.font.ttFont.reader.file.name, + "new_font": new_style.font.ttFont.reader.file.name, + "out": o, + }} + )}) self.run() def __enter__(self): @@ -124,7 +126,7 @@ def ninja_diff( precision: int = FONT_SIZE, no_words: bool = False, no_tables: bool = False, - template = resource_filename( + diffenator_template = resource_filename( "diffenator2", os.path.join("templates", "diffenator.html") ), command="diff", diff --git a/src/diffenator2/__main__.py b/src/diffenator2/__main__.py index fa61deb..1bc3a1d 100644 --- a/src/diffenator2/__main__.py +++ b/src/diffenator2/__main__.py @@ -54,7 +54,7 @@ def main(**kwargs): diff_parser.add_argument("--no-tables", action="store_true", help="Skip diffing font tables") diff_parser.add_argument("--no-words", action="store_true", help="Skip diffing wordlists") parser.add_argument( - "--template", + "--diffenator-template", default=resource_filename( "diffenator2", os.path.join("templates", "diffenator.html") ), diff --git a/src/diffenator2/_diffenator.py b/src/diffenator2/_diffenator.py index 5ec5c9f..8b27de4 100755 --- a/src/diffenator2/_diffenator.py +++ b/src/diffenator2/_diffenator.py @@ -112,7 +112,7 @@ def main(): characters = re_filter_characters(new_font, args.characters) diff.filter_characters(characters) - diff.to_html(args.template, args.out) + diff.to_html(args.diffenator_template, args.out) if __name__ == "__main__":