Repository: googlefonts/ufo2ft
Pull request #766 (2023-07-19 14:29:27)

[instructionCompiler] make 'Number of components differ' logging less noisy
We should only issue this warning when USE_MY_METRICS flags are set manually from the UFO (autoUseMyMetrics=False)
Fixes https://github.com/googlefonts/ufo2ft/issues/743


Patch:
diff --git a/Lib/ufo2ft/instructionCompiler.py b/Lib/ufo2ft/instructionCompiler.py
index 989a515..4353f9a 100644
--- a/Lib/ufo2ft/instructionCompiler.py
+++ b/Lib/ufo2ft/instructionCompiler.py
@@ -39,6 +39,11 @@ class InstructionCompiler:
         if not autoUseMyMetrics:
             # If autoUseMyMetrics is False, replace the method with a no-op
             self.autoUseMyMetrics = lambda ttGlyph, glyphName: None
+        # Only warn--that a glyph's number of components are different in TTFont
+        # vs original UFO--when the USE_MY_METRICS flags are set manually, don't
+        # bother when automatically set:
+        # https://github.com/googlefonts/ufo2ft/issues/743
+        self.warn_if_components_mismatch = not autoUseMyMetrics
 
     def _check_glyph_hash(
         self, glyphName: str, ttglyph: TTGlyph, glyph_hash: Optional[str]
@@ -176,13 +181,14 @@ class InstructionCompiler:
         # Set component flags
 
         if len(ttglyph.components) != len(glyph.components):
-            # May happen if nested components have been flattened by a filter
-            logger.error(
-                "Number of components differ between UFO and TTF "
-                f"in glyph '{glyph.name}' ({len(glyph.components)} vs. "
-                f"{len(ttglyph.components)}, not setting component flags from"
-                "UFO. They may still be set heuristically."
-            )
+            if self.warn_if_components_mismatch:
+                # May happen if nested components have been flattened by a filter
+                logger.error(
+                    "Number of components differ between UFO and TTF "
+                    f"in glyph '{glyph.name}' ({len(glyph.components)} vs. "
+                    f"{len(ttglyph.components)}, not setting component flags from"
+                    "UFO. They may still be set heuristically."
+                )
             self.autoUseMyMetrics(ttglyph, glyph.name)
             return
 


Test patch:
diff --git a/tests/instructionCompiler_test.py b/tests/instructionCompiler_test.py
index 84cfd8b..7d2d792 100644
--- a/tests/instructionCompiler_test.py
+++ b/tests/instructionCompiler_test.py
@@ -566,6 +566,28 @@ class InstructionCompilerTest:
         assert not ttglyph.components[0].flags & USE_MY_METRICS
         assert not ttglyph.components[1].flags & USE_MY_METRICS
 
+    @pytest.mark.parametrize("autoUseMyMetrics", [True, False])
+    def test_set_composite_flags_auto_use_my_metrics_warn_if_components_mismatch(
+        self, quadufo, quadfont, autoUseMyMetrics, caplog
+    ):
+        # check we only log error message for component number mismatch when NOT setting
+        # USE_MY_METRICS flags automatically (otherwise it'd be unintended noise)
+        do_issue_warning = not autoUseMyMetrics
+
+        ic = InstructionCompiler(quadufo, quadfont, autoUseMyMetrics=autoUseMyMetrics)
+        name = "h"
+
+        glyph = quadufo[name]
+        ttglyph = quadfont["glyf"][name]
+        assert len(glyph.components) == len(ttglyph.components)
+        glyph.clearComponents()  # to produce an artificial len(components) mismatch
+        assert len(glyph.components) != len(ttglyph.components)
+
+        with caplog.at_level(logging.ERROR, logger="ufo2ft.instructionCompiler"):
+            ic._set_composite_flags(glyph=glyph, ttglyph=ttglyph)
+
+        assert ("Number of components differ" in caplog.text) is do_issue_warning
+
     # update_maxp
 
     def test_update_maxp_no_ttdata(self, quaduforeversed, quadfont):