Merge pull request #2114 from fonttools/ufolib-add-expect-contents-file

Add expectContentsFile parameter to GlyphSet
This commit is contained in:
Nikolaus Waxweiler 2020-11-23 15:23:26 +00:00 committed by GitHub
commit 6de6ff1050
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
4 changed files with 67 additions and 3 deletions

View File

@ -723,6 +723,7 @@ class UFOReader(_UFOBaseIO):
ufoFormatVersion=self._formatVersion,
validateRead=validateRead,
validateWrite=validateWrite,
expectContentsFile=True
)
def getCharacterMapping(self, layerName=None, validate=None):
@ -1422,7 +1423,15 @@ class UFOWriter(UFOReader):
raise UFOLibError("Could not locate a glyph set directory for the layer named %s." % layerName)
return foundDirectory
def getGlyphSet(self, layerName=None, defaultLayer=True, glyphNameToFileNameFunc=None, validateRead=None, validateWrite=None):
def getGlyphSet(
self,
layerName=None,
defaultLayer=True,
glyphNameToFileNameFunc=None,
validateRead=None,
validateWrite=None,
expectContentsFile=False,
):
"""
Return the GlyphSet object associated with the
appropriate glyph directory in the .ufo.
@ -1435,6 +1444,10 @@ class UFOWriter(UFOReader):
class's validate value, can be overridden.
``validateWrte`` will validate the written data, by default it is set to the
class's validate value, can be overridden.
``expectContentsFile`` will raise a GlifLibError if a contents.plist file is
not found on the glyph set file system. This should be set to ``True`` if you
are reading an existing UFO and ``False`` if you use ``getGlyphSet`` to create
a fresh glyph set.
"""
if validateRead is None:
validateRead = self._validate
@ -1459,7 +1472,12 @@ class UFOWriter(UFOReader):
raise UFOLibError("A layer name must be provided for non-default layers.")
# move along to format specific writing
if self._formatVersion < UFOFormatVersion.FORMAT_3_0:
return self._getDefaultGlyphSet(validateRead, validateWrite, glyphNameToFileNameFunc=glyphNameToFileNameFunc)
return self._getDefaultGlyphSet(
validateRead,
validateWrite,
glyphNameToFileNameFunc=glyphNameToFileNameFunc,
expectContentsFile=expectContentsFile
)
elif self._formatVersion.major == UFOFormatVersion.FORMAT_3_0.major:
return self._getGlyphSetFormatVersion3(
validateRead,
@ -1467,11 +1485,18 @@ class UFOWriter(UFOReader):
layerName=layerName,
defaultLayer=defaultLayer,
glyphNameToFileNameFunc=glyphNameToFileNameFunc,
expectContentsFile=expectContentsFile,
)
else:
raise NotImplementedError(self._formatVersion)
def _getDefaultGlyphSet(self, validateRead, validateWrite, glyphNameToFileNameFunc=None):
def _getDefaultGlyphSet(
self,
validateRead,
validateWrite,
glyphNameToFileNameFunc=None,
expectContentsFile=False,
):
from fontTools.ufoLib.glifLib import GlyphSet
glyphSubFS = self.fs.makedir(DEFAULT_GLYPHS_DIRNAME, recreate=True)
@ -1481,6 +1506,7 @@ class UFOWriter(UFOReader):
ufoFormatVersion=self._formatVersion,
validateRead=validateRead,
validateWrite=validateWrite,
expectContentsFile=expectContentsFile,
)
def _getGlyphSetFormatVersion3(
@ -1490,6 +1516,7 @@ class UFOWriter(UFOReader):
layerName=None,
defaultLayer=True,
glyphNameToFileNameFunc=None,
expectContentsFile=False,
):
from fontTools.ufoLib.glifLib import GlyphSet
@ -1529,6 +1556,7 @@ class UFOWriter(UFOReader):
ufoFormatVersion=self._formatVersion,
validateRead=validateRead,
validateWrite=validateWrite,
expectContentsFile=expectContentsFile,
)
def renameGlyphSet(self, layerName, newLayerName, defaultLayer=False):

View File

@ -135,6 +135,7 @@ class GlyphSet(_UFOBaseIO):
ufoFormatVersion=None,
validateRead=True,
validateWrite=True,
expectContentsFile=False,
):
"""
'path' should be a path (string) to an existing local directory, or
@ -148,6 +149,9 @@ class GlyphSet(_UFOBaseIO):
``validateRead`` will validate read operations. Its default is ``True``.
``validateWrite`` will validate write operations. Its default is ``True``.
``expectContentsFile`` will raise a GlifLibError if a contents.plist file is
not found on the glyph set file system. This should be set to ``True`` if you
are reading an existing UFO and ``False`` if you create a fresh glyph set.
"""
try:
ufoFormatVersion = UFOFormatVersion(ufoFormatVersion)
@ -191,6 +195,8 @@ class GlyphSet(_UFOBaseIO):
self.fs = filesystem
# if glyphSet contains no 'contents.plist', we consider it empty
self._havePreviousFile = filesystem.exists(CONTENTS_FILENAME)
if expectContentsFile and not self._havePreviousFile:
raise GlifLibError(f"{CONTENTS_FILENAME} is missing.")
# attribute kept for backward compatibility
self.ufoFormatVersion = ufoFormatVersion.major
self.ufoFormatVersionTuple = ufoFormatVersion

View File

@ -3940,6 +3940,26 @@ class UFO3WriteLayersTestCase(unittest.TestCase):
result = list(writer.getGlyphSet("layer 2", defaultLayer=False).keys())
self.assertEqual(expected, result)
def testGetGlyphSetNoContents(self):
self.makeUFO()
os.remove(os.path.join(self.ufoPath, "glyphs.layer 1", "contents.plist"))
reader = UFOReader(self.ufoPath, validate=True)
with self.assertRaises(GlifLibError):
reader.getGlyphSet("layer 1")
writer = UFOWriter(self.ufoPath, validate=True)
with self.assertRaises(GlifLibError):
writer.getGlyphSet("layer 1", defaultLayer=False, expectContentsFile=True)
# There's a separate code path for < v3 UFOs.
with open(os.path.join(self.ufoPath, "metainfo.plist"), "wb") as f:
plistlib.dump(dict(creator="test", formatVersion=2), f)
os.remove(os.path.join(self.ufoPath, "glyphs", "contents.plist"))
writer = UFOWriter(self.ufoPath, validate=True, formatVersion=2)
with self.assertRaises(GlifLibError):
writer.getGlyphSet(expectContentsFile=True)
# make a new font with two layers
def testNewFontOneLayer(self):

View File

@ -54,6 +54,16 @@ class GlyphSetTests(unittest.TestCase):
added, removed,
"%s.glif file differs after round tripping" % glyphName)
def testContentsExist(self):
with self.assertRaises(GlifLibError):
GlyphSet(
self.dstDir,
ufoFormatVersion=2,
validateRead=True,
validateWrite=True,
expectContentsFile=True,
)
def testRebuildContents(self):
gset = GlyphSet(GLYPHSETDIR, validateRead=True, validateWrite=True)
contents = gset.contents