def test_loadFilters_args_missing(ufo): del ufo.lib[UFO2FT_FILTERS_KEY][0]["args"] with pytest.raises(TypeError) as exc_info: loadFilters(ufo) assert exc_info.match("missing")
def test_loadFilters_failed(ufo): ufo.lib[UFO2FT_FILTERS_KEY].append(dict(name="Non Existent")) with CapturingLogHandler(logger, level="ERROR") as captor: loadFilters(ufo) captor.assertRegex("Failed to load filter")
def test_loadFilters_args_unsupported(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["args"].append("baz") with pytest.raises(TypeError) as exc_info: loadFilters(ufo) assert exc_info.match('unsupported')
def test_loadFilters_both_include_exclude(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["include"] = ["a", "b"] ufo.lib[UFO2FT_FILTERS_KEY][0]["exclude"] = ["c", "d"] with pytest.raises(ValueError) as exc_info: loadFilters(ufo) assert exc_info.match("arguments are mutually exclusive")
def test_loadFilters_args_as_duplicated_keywords(ufo): ufo.lib[FILTERS_KEY][0]["args"] = ["foo"] ufo.lib[FILTERS_KEY][0]["kwargs"] = {"a": "foo", "b": "bar"} with pytest.raises(TypeError) as exc_info: loadFilters(ufo) assert exc_info.match("duplicated")
def test_loadFilters_kwargs_unsupported(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["kwargs"] = {} ufo.lib[UFO2FT_FILTERS_KEY][0]["kwargs"]["c"] = 1 ufo.lib[UFO2FT_FILTERS_KEY][0]["kwargs"]["d"] = 2 # unknown with pytest.raises(TypeError) as exc_info: loadFilters(ufo) assert exc_info.match("got an unsupported keyword")
def __init__(self, ufo, inplace=False, layerName=None, **kwargs): self.ufo = ufo self.inplace = inplace self.layerName = layerName self.glyphSet = _GlyphSet.from_layer(ufo, layerName, copy=not inplace) self.defaultFilters = self.initDefaultFilters(**kwargs) self.preFilters, self.postFilters = loadFilters(ufo)
def __init__(self, ufo, inplace=False, **kwargs): self.ufo = ufo if inplace: self.glyphSet = {g.name: g for g in ufo} else: self.glyphSet = {g.name: _copyGlyph(g) for g in ufo} self.defaultFilters = self.initDefaultFilters(**kwargs) self.preFilters, self.postFilters = loadFilters(ufo)
def test_loadFilters_exclude_list(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["exclude"] = ["a", "b"] _, [filter_obj] = loadFilters(ufo) assert not filter_obj.include(MockGlyph(name="a")) assert not filter_obj.include(MockGlyph(name="b")) assert filter_obj.include(MockGlyph(name="c"))
def test_loadFilters_args_as_keywords(ufo): del ufo.lib[FILTERS_KEY][0]["args"] ufo.lib[FILTERS_KEY][0]["kwargs"] = {"a": "foo", "b": "bar"} _, [filter_obj] = loadFilters(ufo) assert filter_obj.options.a == "foo" assert filter_obj.options.b == "bar"
def __init__( self, ufos, inplace=False, flattenComponents=False, conversionError=None, reverseDirection=True, rememberCurveType=True, layerNames=None, skipExportGlyphs=None, filters=None, ): from cu2qu.ufo import DEFAULT_MAX_ERR self.ufos = ufos self.inplace = inplace self.flattenComponents = flattenComponents if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) self.layerNames = layerNames self.glyphSets = [ _GlyphSet.from_layer( ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs ) for ufo, layerName in zip(ufos, layerNames) ] self._conversionErrors = [ (conversionError or DEFAULT_MAX_ERR) * getAttrWithFallback(ufo.info, "unitsPerEm") for ufo in ufos ] self._reverseDirection = reverseDirection self._rememberCurveType = rememberCurveType self.preFilters, self.postFilters = [], [] if filters is None: for ufo in ufos: pre, post = loadFilters(ufo) self.preFilters.append(pre) self.postFilters.append(post) else: pre = [f for f in filters if f.pre] post = [f for f in filters if not f.pre] for _ in ufos: self.preFilters.append(pre) self.postFilters.append(post)
def test_loadFilters_custom_namespace(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["name"] = "Self Destruct" ufo.lib[UFO2FT_FILTERS_KEY][0]["namespace"] = "my_dangerous_filters" class SelfDestructFilter(FooBarFilter): def filter(glyph): # Don't try this at home!!! LOL :) # shutil.rmtree(os.path.expanduser("~")) return True with _TempModule("my_dangerous_filters"), \ _TempModule("my_dangerous_filters.selfDestruct") as temp: temp.module.__dict__["SelfDestructFilter"] = SelfDestructFilter _, [filter_obj] = loadFilters(ufo) assert isinstance(filter_obj, SelfDestructFilter)
def __init__( self, ufo, inplace=False, layerName=None, skipExportGlyphs=None, filters=None, **kwargs ): self.ufo = ufo self.inplace = inplace self.layerName = layerName self.glyphSet = _GlyphSet.from_layer( ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs ) self.defaultFilters = self.initDefaultFilters(**kwargs) if filters is None: self.preFilters, self.postFilters = loadFilters(ufo) else: self.preFilters = [f for f in filters if f.pre] self.postFilters = [f for f in filters if not f.pre]
def __init__( self, ufos, inplace=False, conversionError=None, reverseDirection=True, rememberCurveType=True, layerNames=None, skipExportGlyphs=None, ): from cu2qu.ufo import DEFAULT_MAX_ERR self.ufos = ufos self.inplace = inplace if layerNames is None: layerNames = [None] * len(ufos) assert len(ufos) == len(layerNames) self.layerNames = layerNames self.glyphSets = [ _GlyphSet.from_layer(ufo, layerName, copy=not inplace, skipExportGlyphs=skipExportGlyphs) for ufo, layerName in zip(ufos, layerNames) ] self._conversionErrors = [ (conversionError or DEFAULT_MAX_ERR) * ufo.info.unitsPerEm for ufo in ufos ] self._reverseDirection = reverseDirection self._rememberCurveType = rememberCurveType self.preFilters, self.postFilters = [], [] for ufo in ufos: pre, post = loadFilters(ufo) self.preFilters.append(pre) self.postFilters.append(post)
def test_loadFilters_pre(ufo): ufo.lib[UFO2FT_FILTERS_KEY][0]["pre"] = True pre, post = loadFilters(ufo) assert len(pre) == 1 assert not post assert isinstance(pre[0], FooBarFilter)
def test_loadFilters_empty(): ufo = MockFont(lib={}) assert UFO2FT_FILTERS_KEY not in ufo.lib assert loadFilters(ufo) == ([], [])
def run_from_designspace( self, designspace_path, output=(), interpolate=False, masters_as_instances=False, interpolate_binary_layout=False, round_instances=False, feature_writers=None, filters=None, expand_features_to_instances=False, use_mutatormath=False, **kwargs, ): """Run toolchain from a DesignSpace document to produce either static instance fonts (ttf or otf), interpolatable or variable fonts. Args: designspace_path: Path to designspace document. interpolate: If True output all instance fonts, otherwise just masters. If the value is a string, only build instance(s) that match given name. The string is compiled into a regular expression and matched against the "name" attribute of designspace instances using `re.fullmatch`. masters_as_instances: If True, output master fonts as instances. interpolate_binary_layout: Interpolate layout tables from compiled master binaries. round_instances: apply integer rounding when interpolating with MutatorMath. kwargs: Arguments passed along to run_from_ufos. Raises: TypeError: "variable" or "interpolatable" outputs are incompatible with arguments "interpolate", "masters_as_instances", and "interpolate_binary_layout". """ interp_outputs = INTERPOLATABLE_OUTPUTS.intersection(output) static_outputs = set(output).difference(interp_outputs) if interp_outputs: for argname in ( "interpolate", "masters_as_instances", "interpolate_binary_layout", ): if locals()[argname]: raise TypeError( '"%s" argument incompatible with output %r' % (argname, ", ".join(sorted(interp_outputs))) ) try: designspace = designspaceLib.DesignSpaceDocument.fromfile(designspace_path) except Exception as e: raise FontmakeError("Reading Designspace failed", designspace_path) from e # if no --feature-writers option was passed, check in the designspace's # <lib> element if user supplied a custom featureWriters configuration; # if so, use that for all the UFOs built from this designspace if feature_writers is None and FEATURE_WRITERS_KEY in designspace.lib: feature_writers = loadFeatureWriters(designspace) if filters is None and FILTERS_KEY in designspace.lib: preFilters, postFilters = loadFilters(designspace) filters = preFilters + postFilters try: if static_outputs: self._run_from_designspace_static( designspace, outputs=static_outputs, interpolate=interpolate, masters_as_instances=masters_as_instances, interpolate_binary_layout=interpolate_binary_layout, round_instances=round_instances, feature_writers=feature_writers, expand_features_to_instances=expand_features_to_instances, use_mutatormath=use_mutatormath, filters=filters, **kwargs, ) if interp_outputs: self._run_from_designspace_interpolatable( designspace, outputs=interp_outputs, feature_writers=feature_writers, filters=filters, **kwargs, ) except FontmakeError as e: # Some called functions already added the Designspace file to the source # trail. if e.source_trail[-1] != designspace.path: e.source_trail.append(designspace.path) raise except Exception as e: raise FontmakeError( "Generating fonts from Designspace failed", designspace.path ) from e
def test_loadFilters_include_all(ufo): _, [filter_obj] = loadFilters(ufo) assert filter_obj.include(MockGlyph(name="hello")) assert filter_obj.include(MockGlyph(name="world"))