diff --git a/Lib/fontTools/designspaceLib/__init__.py b/Lib/fontTools/designspaceLib/__init__.py index 24c2247ff..f92273090 100644 --- a/Lib/fontTools/designspaceLib/__init__.py +++ b/Lib/fontTools/designspaceLib/__init__.py @@ -673,12 +673,6 @@ class BaseDocReader(LogMixin): self.readInstances() self.readLib() - def getSourcePaths(self, makeGlyphs=True, makeKerning=True, makeInfo=True): - paths = [] - for name in self.documentObject.sources.keys(): - paths.append(self.documentObject.sources[name][0].path) - return paths - def readRules(self): # we also need to read any conditions that are outside of a condition set. rules = [] @@ -1278,3 +1272,30 @@ class DesignSpaceDocument(LogMixin, AsDictMixin): newConditions.append(dict(name=cond['name'], minimum=minimum, maximum=maximum)) newConditionSets.append(newConditions) rule.conditionSets = newConditionSets + + def getSourcePath(self, sourceDescriptor): + """Return the absolute path of sourceDescriptor. This is either the + 'path' attribute, or if the latter is not set, the concatenation of + the source's (relative) 'filename' attribute and the designspace's + directory. + + Raises DesignSpaceDocumentError if sourceDescriptor.path is None and + self.path is None, or sourceDescriptor.filename is None. + """ + if sourceDescriptor.path: + # prefer absolute path if present + return sourceDescriptor.path + if self.path is None: + raise DesignSpaceDocumentError( + "DesignSpaceDocument 'path' attribute is not defined; cannot " + "load source from relative filename" + ) + if sourceDescriptor.filename is None: + raise DesignSpaceDocumentError( + "Designspace source '%s' has neither absolute 'path' nor " + "relative 'filename' defined" + % (sourceDescriptor.name or "") + ) + return os.path.abspath( + os.path.join(os.path.dirname(self.path), sourceDescriptor.filename) + ) diff --git a/Lib/fontTools/varLib/__init__.py b/Lib/fontTools/varLib/__init__.py index ba5307136..50b26f18b 100644 --- a/Lib/fontTools/varLib/__init__.py +++ b/Lib/fontTools/varLib/__init__.py @@ -809,26 +809,6 @@ def build(designspace, master_finder=lambda s:s, exclude=[], optimize=True): return vf, model, master_ttfs -# TODO: move to designspaceLib? -def _get_master_path(designspace, master): - if master.path: - # prefer absolute path if present - return master.path - if designspace.path is None: - raise AttributeError( - "DesignSpaceDocument 'path' attribute is not defined; cannot " - "load master from relative filename" - ) - if master.filename is None: - raise AttributeError( - "Designspace source '%s' has neither absolute 'path' nor " - "relative 'filename' defined" - % (master.name or "") - ) - return os.path.join(os.path.dirname(designspace.path), master.filename) - - - def load_masters(designspace, master_finder=lambda s: s): """Ensure that all SourceDescriptor.font attributes have an appropriate TTFont object loaded. @@ -855,7 +835,7 @@ def load_masters(designspace, master_finder=lambda s: s): else: # 2. A SourceDescriptor's filename might point to a UFO or an OpenType # binary. Find out the hard way. - master_path = _get_master_path(designspace, master) + master_path = designspace.getSourcePath(master) try: font = TTFont(master_path) except (IOError, TTLibError): diff --git a/Tests/designspaceLib/designspace_test.py b/Tests/designspaceLib/designspace_test.py index 5669093ca..bd5358886 100644 --- a/Tests/designspaceLib/designspace_test.py +++ b/Tests/designspaceLib/designspace_test.py @@ -785,3 +785,28 @@ def test_documentLib(tmpdir): assert dummyKey in new.lib assert new.lib[dummyKey] == dummyData + +def test_getSourcePath(): + doc = DesignSpaceDocument() + s1 = SourceDescriptor() + + with pytest.raises( + DesignSpaceDocumentError, + match="DesignSpaceDocument 'path' attribute is not defined", + ): + doc.getSourcePath(s1) + + doc.path = "/tmp/foo/bar/MyDesignspace.designspace" + + with pytest.raises( + DesignSpaceDocumentError, + match=( + "Designspace source '' has neither absolute 'path' nor " + "relative 'filename' defined" + ), + ): + doc.getSourcePath(s1) + + s1.filename = "../masters/Source1.ufo" + + assert doc.getSourcePath(s1) == "/tmp/foo/masters/Source1.ufo"