nebius/SWE-rebench-V2-PRs huggingface dataset:
Repository: googlefonts/ufo2ft
Pull request #715 (2023-02-28 18:17:53)

Deal with "Filter" suffix of filter names
Deal with the fact that the `DottedCircleFilter` class is misnamed by stripping the "Filter" when searching for the module.

Closes https://github.com/googlefonts/ufo2ft/issues/707


Patch:
diff --git a/Lib/ufo2ft/filters/__init__.py b/Lib/ufo2ft/filters/__init__.py
index 912f337..bc813c7 100644
--- a/Lib/ufo2ft/filters/__init__.py
+++ b/Lib/ufo2ft/filters/__init__.py
@@ -45,6 +45,8 @@ def getFilterClass(filterName, pkg="ufo2ft.filters"):
     # TODO add support for third-party plugin discovery?
     # if filter name is 'Foo Bar', the module should be called 'fooBar'
     filterName = filterName.replace(" ", "")
+    if filterName.endswith("Filter"):
+        filterName = filterName[: -len("Filter")]
     moduleName = filterName[0].lower() + filterName[1:]
     module = importlib.import_module(".".join([pkg, moduleName]))
     # if filter name is 'Foo Bar', the class should be called 'FooBarFilter'


Test patch:
diff --git a/tests/filters/dottedCircle_test.py b/tests/filters/dottedCircle_test.py
index 5df478c..980d367 100644
--- a/tests/filters/dottedCircle_test.py
+++ b/tests/filters/dottedCircle_test.py
@@ -1,5 +1,6 @@
 from ufo2ft.filters.dottedCircleFilter import DottedCircleFilter
 from ufo2ft.util import _GlyphSet
+from ufo2ft.filters import loadFilters
 
 
 def test_dotted_circle_filter(FontClass, datadir):
@@ -40,7 +41,12 @@ def test_empty_font(FontClass):
     appropriate."""
 
     font = FontClass()
-    philter = DottedCircleFilter()
+    font.lib["com.github.googlei18n.ufo2ft.filters"] = [
+        {"name": "DottedCircleFilter", "pre": True}
+    ]
+
+    pre_filters, _ = loadFilters(font)
+    (philter,) = pre_filters
     glyphset = _GlyphSet.from_layer(font)
 
     modified = philter(font, glyphset)
diff --git a/tests/filters/filters_test.py b/tests/filters/filters_test.py
index 2fe9ab3..be2425e 100644
--- a/tests/filters/filters_test.py
+++ b/tests/filters/filters_test.py
@@ -38,6 +38,7 @@ def fooBar():
 def test_getFilterClass():
     assert getFilterClass("Foo Bar") == FooBarFilter
     assert getFilterClass("FooBar") == FooBarFilter
+    assert getFilterClass("FooBarFilter") == FooBarFilter
     assert getFilterClass("fooBar") == FooBarFilter
     with pytest.raises(ImportError):
         getFilterClass("Baz")
Repository: googlefonts/ufo2ft
Pull request #780 (2023-09-08 17:02:47)

instructionCompiler: don't log about .notdef missing
I keep seing logging messages like this coming from ufo2ft.instructionCompiler

```
INFO:ufo2ft.instructionCompiler:Skipping compilation of instructions for glyph '.notdef' because it is not in the input UFO.
```

this is just noise and may also be confusing for the user. ".notdef" glyph is very often automatically generated by ufo2ft, in which case obviously it's because it is missing from the source UFOs, and so there's no need for the instructionCompiler to be chatty about it.


Patch:
diff --git a/Lib/ufo2ft/instructionCompiler.py b/Lib/ufo2ft/instructionCompiler.py
index 32ed8fb..86887e3 100644
--- a/Lib/ufo2ft/instructionCompiler.py
+++ b/Lib/ufo2ft/instructionCompiler.py
@@ -109,11 +109,13 @@ class InstructionCompiler:
         """Compile the glyph instructions from the UFO glyph `name` to bytecode
         and add it to `ttGlyph`."""
         if name not in self.ufo:
-            # Skip glyphs that are not in the UFO, e.g. '.notdef'
-            logger.info(
-                f"Skipping compilation of instructions for glyph '{name}' because it "
-                "is not in the input UFO."
-            )
+            # Skip glyphs that are not in the UFO; no need to inform about '.notdef'
+            # since that glyph is often auto-generated
+            if name != ".notdef":
+                logger.info(
+                    f"Skipping compilation of instructions for glyph '{name}' because it "
+                    "is not in the input UFO."
+                )
             return
 
         glyph = self.ufo[name]


Test patch:
diff --git a/tests/instructionCompiler_test.py b/tests/instructionCompiler_test.py
index 00a2c75..87d2d66 100644
--- a/tests/instructionCompiler_test.py
+++ b/tests/instructionCompiler_test.py
@@ -281,11 +281,18 @@ class InstructionCompilerTest:
 
     def test_compileGlyphInstructions_missing_glyph(self, caplog):
         # The method logs an info when trying to compile a glyph which is
-        # missing in the UFO, e.g. '.notdef'
+        # missing in the UFO
         ic = InstructionCompiler(dict(), None)
         with caplog.at_level(logging.INFO, logger="ufo2ft.instructionCompiler"):
             ic.compileGlyphInstructions(None, "A")
         assert "Skipping compilation of instructions for glyph 'A'" in caplog.text
+        # ... except for '.notdef' which is frequently generated
+        with caplog.at_level(logging.INFO, logger="ufo2ft.instructionCompiler"):
+            ic.compileGlyphInstructions(None, ".notdef")
+        assert (
+            "Skipping compilation of instructions for glyph '.notdef'"
+            not in caplog.text
+        )
 
     # _compile_tt_glyph_program
Repository: googlefonts/ufo2ft
Pull request #864 (2024-08-28 19:39:33)

Fix the order of feature writers
We want curs feature lookups to come first, then kerning, then mark/mkmk, but we currently are calling CursFeatureWriter last which causes its lookups to be also written last. The lookup order does not matter for HarfBuzz, but it matters for other implementations, see: https://github.com/harfbuzz/harfbuzz/issues/4596#issuecomment-2220558649


Patch:
diff --git a/Lib/ufo2ft/featureCompiler.py b/Lib/ufo2ft/featureCompiler.py
index 8af6318..f18621a 100644
--- a/Lib/ufo2ft/featureCompiler.py
+++ b/Lib/ufo2ft/featureCompiler.py
@@ -172,10 +172,10 @@ class FeatureCompiler(BaseFeatureCompiler):
     """
 
     defaultFeatureWriters = [
+        CursFeatureWriter,
         KernFeatureWriter,
         MarkFeatureWriter,
         GdefFeatureWriter,
-        CursFeatureWriter,
     ]
 
     def __init__(


Test patch:
diff --git a/tests/featureWriters/variableFeatureWriter_test.py b/tests/featureWriters/variableFeatureWriter_test.py
index b501c03..9217a7b 100644
--- a/tests/featureWriters/variableFeatureWriter_test.py
+++ b/tests/featureWriters/variableFeatureWriter_test.py
@@ -19,6 +19,16 @@ def test_variable_features(FontClass):
         markClass dotabove-ar <anchor (wght=100:100 wght=1000:125) (wght=100:320 wght=1000:416)> @MC_top;
         markClass gravecmb <anchor 250 400> @MC_top;
 
+        feature curs {
+            lookup curs_rtl {
+                lookupflag RightToLeft IgnoreMarks;
+                pos cursive alef-ar.fina <anchor (wght=100:299 wght=1000:330) (wght=100:97 wght=1000:115)> <anchor NULL>;
+                pos cursive peh-ar.init <anchor NULL> <anchor (wght=100:161 wght=1000:73) (wght=100:54 wght=1000:89)>;
+                pos cursive peh-ar.init.BRACKET.varAlt01 <anchor NULL> <anchor (wght=100:89 wght=1000:73) (wght=100:53 wght=1000:85)>;
+            } curs_rtl;
+
+        } curs;
+
         lookup kern_Arab {
             lookupflag IgnoreMarks;
             pos alef-ar.fina alef-ar.fina <(wght=100:15 wght=1000:35) 0 (wght=100:15 wght=1000:35) 0>;
@@ -47,16 +57,6 @@ def test_variable_features(FontClass):
         table GDEF {
             LigatureCaretByPos peh-ar.init 100;
         } GDEF;
-
-        feature curs {
-            lookup curs_rtl {
-                lookupflag RightToLeft IgnoreMarks;
-                pos cursive alef-ar.fina <anchor (wght=100:299 wght=1000:330) (wght=100:97 wght=1000:115)> <anchor NULL>;
-                pos cursive peh-ar.init <anchor NULL> <anchor (wght=100:161 wght=1000:73) (wght=100:54 wght=1000:89)>;
-                pos cursive peh-ar.init.BRACKET.varAlt01 <anchor NULL> <anchor (wght=100:89 wght=1000:73) (wght=100:53 wght=1000:85)>;
-            } curs_rtl;
-
-        } curs;
 """  # noqa: B950
     )
Repository: googlefonts/ufo2ft
Pull request #887 (2024-11-14 15:01:17)

[instantiator] use designspace.findDefault() the first time designspace.default is checked
otherwise a DS object that was created from code has a 'default' attribute set to None (until findDefault() is first called).
Those loaded from string or file have that set automatically by the respective constructors.


Patch:
diff --git a/Lib/ufo2ft/instantiator.py b/Lib/ufo2ft/instantiator.py
index 067eb1f..fcc7f97 100644
--- a/Lib/ufo2ft/instantiator.py
+++ b/Lib/ufo2ft/instantiator.py
@@ -251,7 +251,7 @@ class Instantiator:
         do_glyphs=True,
     ):
         """Instantiates a new data class from a Designspace object."""
-        if designspace.default is None:
+        if designspace.findDefault() is None:
             raise InstantiatorError(_error_msg_no_default(designspace))
 
         if any(hasattr(axis, "values") for axis in designspace.axes):


Test patch:
diff --git a/tests/instantiator_test.py b/tests/instantiator_test.py
index 6112db2..fa67331 100644
--- a/tests/instantiator_test.py
+++ b/tests/instantiator_test.py
@@ -71,7 +71,6 @@ def test_default_groups_only(ufo_module, data_dir, caplog):
     d.addSourceDescriptor(location={"Weight": 300}, font=ufo_module.Font())
     d.addSourceDescriptor(location={"Weight": 900}, font=ufo_module.Font())
     d.addInstanceDescriptor(styleName="2", location={"Weight": 400})
-    d.findDefault()
 
     d.sources[0].font.groups["public.kern1.GRK_alpha_alt_LC_1ST"] = [
         "alpha.alt",
@@ -102,7 +101,6 @@ def test_default_groups_only2(ufo_module, data_dir, caplog):
     d.addSourceDescriptor(location={"Weight": 300}, font=ufo_module.Font())
     d.addSourceDescriptor(location={"Weight": 900}, font=ufo_module.Font())
     d.addInstanceDescriptor(styleName="2", location={"Weight": 400})
-    d.findDefault()
 
     d.sources[0].font.groups["public.kern1.GRK_alpha_alt_LC_1ST"] = [
         "alpha.alt",