Add in more valiator switches

This commit is contained in:
Ben Kiel 2018-06-11 23:13:00 -05:00
parent 4c75212ee6
commit 83303d56a7
4 changed files with 169 additions and 142 deletions

View File

@ -151,7 +151,7 @@ class UFOReader(object):
``validate`` will validate the data.
"""
if self._upConvertedKerningData:
if validate and self._upConvertedKerningData:
testKerning = self._readKerning()
if testKerning != self._upConvertedKerningData["originalKerning"]:
raise UFOLibError("The data in kerning.plist has been modified since it was converted to UFO 3 format.")
@ -326,9 +326,9 @@ class UFOReader(object):
# fontinfo.plist
def _readInfo(self):
def _readInfo(self, validate):
data = self._getPlist(FONTINFO_FILENAME, {})
if not isinstance(data, dict):
if validate and not isinstance(data, dict):
raise UFOLibError("fontinfo.plist is not properly formatted.")
return data
@ -344,7 +344,7 @@ class UFOReader(object):
"""
if validate is None:
validate = self._validate
infoDict = self._readInfo()
infoDict = self._readInfo(validate)
infoDataToSet = {}
# version 1
if self._formatVersion == 1:
@ -493,7 +493,8 @@ class UFOReader(object):
if layerDirectory == DEFAULT_GLYPHS_DIRNAME:
return layerName
# this will already have been raised during __init__
raise UFOLibError("The default layer is not defined in layercontents.plist.")
if validate:
raise UFOLibError("The default layer is not defined in layercontents.plist.")
def getGlyphSet(self, layerName=None, validateRead=None, validateWrite=None):
"""
@ -615,10 +616,10 @@ class UFOReader(object):
"""
if validate is None:
validate = self._validate
if self._formatVersion < 3:
if validate and self._formatVersion < 3:
raise UFOLibError("Reading images is not allowed in UFO %d." % self._formatVersion)
data = self.readBytesFromPath(os.path.join(IMAGES_DIRNAME, fileName))
if data is None:
if validate and data is None:
raise UFOLibError("No image file named %s." % fileName)
if validate:
valid, error = pngValidator(data=data)
@ -661,10 +662,10 @@ class UFOWriter(object):
previousFormatVersion = int(previousFormatVersion)
except:
raise UFOLibError("The existing metainfo.plist is not properly formatted.")
if previousFormatVersion not in supportedUFOFormatVersions:
if validate and previousFormatVersion not in supportedUFOFormatVersions:
raise UFOLibError("Unsupported UFO format (%d)." % formatVersion)
# catch down conversion
if previousFormatVersion is not None and previousFormatVersion > formatVersion:
if validate and previousFormatVersion is not None and previousFormatVersion > formatVersion:
raise UFOLibError("The UFO located at this path is a higher version (%d) than the version (%d) that is trying to be written. This is not supported." % (previousFormatVersion, formatVersion))
# handle the layer contents
self.layerContents = {}
@ -1056,15 +1057,18 @@ class UFOWriter(object):
# features.fea
def writeFeatures(self, features):
def writeFeatures(self, features, validate=None):
"""
Write features.fea. This method requires a
features string as an argument.
"""
if self._formatVersion == 1:
raise UFOLibError("features.fea is not allowed in UFO Format Version 1.")
if not isinstance(features, basestring):
raise UFOLibError("The features are not text.")
if validate is None:
validate = self._validate
if validate:
if self._formatVersion == 1:
raise UFOLibError("features.fea is not allowed in UFO Format Version 1.")
if not isinstance(features, basestring):
raise UFOLibError("The features are not text.")
self._makeDirectory()
path = os.path.join(self._path, FEATURES_FILENAME)
writeFileAtomically(features, path)
@ -1090,11 +1094,13 @@ class UFOWriter(object):
contents[layerName] = directoryName
self.layerContents = contents
def writeLayerContents(self, layerOrder=None):
def writeLayerContents(self, layerOrder=None, validate=None):
"""
Write the layercontents.plist file. This method *must* be called
after all glyph sets have been written.
"""
if validate is None:
validate = self._validate
if self.formatVersion < 3:
return
if layerOrder is not None:
@ -1106,7 +1112,7 @@ class UFOWriter(object):
layerOrder = newOrder
else:
layerOrder = list(self.layerContents.keys())
if set(layerOrder) != set(self.layerContents.keys()):
if validate and set(layerOrder) != set(self.layerContents.keys()):
raise UFOLibError("The layer order contents does not match the glyph sets that have been created.")
layerContents = [(layerName, self.layerContents[layerName]) for layerName in layerOrder]
self._writePlist(LAYERCONTENTS_FILENAME, layerContents)
@ -1143,7 +1149,7 @@ class UFOWriter(object):
if validateWrite is None:
validateWrite = self._validate
# only default can be written in < 3
if self._formatVersion < 3 and (not defaultLayer or layerName is not None):
if validateWrite and self._formatVersion < 3 and (not defaultLayer or layerName is not None):
raise UFOLibError("Only the default layer can be writen in UFO %d." % self.formatVersion)
# locate a layer name when None has been given
if layerName is None and defaultLayer:
@ -1152,7 +1158,7 @@ class UFOWriter(object):
layerName = existingLayerName
if layerName is None:
layerName = DEFAULT_LAYER_NAME
elif layerName is None and not defaultLayer:
elif validateWrite and layerName is None and not defaultLayer:
raise UFOLibError("A layer name must be provided for non-default layers.")
# move along to format specific writing
if self.formatVersion == 1:
@ -1175,12 +1181,13 @@ class UFOWriter(object):
# matches the default being written. also make sure that this layer
# name is not already linked to a non-default layer.
if defaultLayer:
for existingLayerName, directory in list(self.layerContents.items()):
if directory == DEFAULT_GLYPHS_DIRNAME:
if existingLayerName != layerName:
raise UFOLibError("Another layer is already mapped to the default directory.")
elif existingLayerName == layerName:
raise UFOLibError("The layer name is already mapped to a non-default layer.")
if validateRead:
for existingLayerName, directory in list(self.layerContents.items()):
if directory == DEFAULT_GLYPHS_DIRNAME:
if existingLayerName != layerName:
raise UFOLibError("Another layer is already mapped to the default directory.")
elif existingLayerName == layerName:
raise UFOLibError("The layer name is already mapped to a non-default layer.")
# get an existing directory name
if layerName in self.layerContents:
directory = self.layerContents[layerName]
@ -1282,24 +1289,30 @@ class UFOWriter(object):
path = os.path.join(IMAGES_DIRNAME, fileName)
self.writeBytesToPath(path, data)
def removeImage(self, fileName):
def removeImage(self, fileName, validate=None):
"""
Remove the file named fileName from the
images directory.
"""
if self._formatVersion < 3:
raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
if validate is None:
validate = self._validate
if validate:
if self._formatVersion < 3:
raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
path = os.path.join(IMAGES_DIRNAME, fileName)
self.removeFileForPath(path)
def copyImageFromReader(self, reader, sourceFileName, destFileName):
def copyImageFromReader(self, reader, sourceFileName, destFileName, validate=None):
"""
Copy the sourceFileName in the provided UFOReader to destFileName
in this writer. This uses the most memory efficient method possible
for copying the data possible.
"""
if self._formatVersion < 3:
raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
if validate is None:
validate = self._validate
if validate:
if self._formatVersion < 3:
raise UFOLibError("Images are not allowed in UFO %d." % self._formatVersion)
sourcePath = os.path.join("images", sourceFileName)
destPath = os.path.join("images", destFileName)
self.copyFromReader(reader, sourcePath, destPath)

View File

@ -202,9 +202,9 @@ class GlyphSet(object):
infoDict = self._readPlist(path)
except MissingPlistError:
return
if not isinstance(infoDict, dict):
raise GlifLibError("layerinfo.plist is not properly formatted.")
if validateRead:
if not isinstance(infoDict, dict):
raise GlifLibError("layerinfo.plist is not properly formatted.")
infoDict = validateLayerInfoVersion3Data(infoDict)
# populate the object
for attr, value in infoDict.items():
@ -220,7 +220,7 @@ class GlyphSet(object):
"""
if validateWrite is None:
validateWrite = self._validateWrite
if self.ufoFormatVersion < 3:
if validateWrite and self.ufoFormatVersion < 3:
raise GlifLibError("layerinfo.plist is not allowed in UFO %d." % self.ufoFormatVersion)
# gather data
infoData = {}
@ -375,7 +375,7 @@ class GlyphSet(object):
formatVersion = 2
else:
formatVersion = 1
else:
elif validate:
if formatVersion not in supportedGLIFFormatVersions:
raise GlifLibError("Unsupported GLIF format version: %s" % formatVersion)
if formatVersion == 2 and self.ufoFormatVersion < 3:
@ -590,20 +590,20 @@ def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, writer=
aFile = None
identifiers = set()
# start
if not isinstance(glyphName, basestring):
if validate and not isinstance(glyphName, basestring):
raise GlifLibError("The glyph name is not properly formatted.")
if len(glyphName) == 0:
if validate and len(glyphName) == 0:
raise GlifLibError("The glyph name is empty.")
writer.begintag("glyph", [("name", glyphName), ("format", formatVersion)])
writer.newline()
# advance
_writeAdvance(glyphObject, writer)
_writeAdvance(glyphObject, writer, validate)
# unicodes
if getattr(glyphObject, "unicodes", None):
_writeUnicodes(glyphObject, writer)
_writeUnicodes(glyphObject, writer, validate)
# note
if getattr(glyphObject, "note", None):
_writeNote(glyphObject, writer)
_writeNote(glyphObject, writer, validate)
# image
if formatVersion >= 2 and getattr(glyphObject, "image", None):
_writeImage(glyphObject, writer, validate)
@ -636,16 +636,16 @@ def writeGlyphToString(glyphName, glyphObject=None, drawPointsFunc=None, writer=
else:
return None
def _writeAdvance(glyphObject, writer):
def _writeAdvance(glyphObject, writer, validate):
width = getattr(glyphObject, "width", None)
if width is not None:
if not isinstance(width, (int, float)):
if validate and not isinstance(width, (int, float)):
raise GlifLibError("width attribute must be int or float")
if width == 0:
width = None
height = getattr(glyphObject, "height", None)
if height is not None:
if not isinstance(height, (int, float)):
if validate and not isinstance(height, (int, float)):
raise GlifLibError("height attribute must be int or float")
if height == 0:
height = None
@ -659,13 +659,13 @@ def _writeAdvance(glyphObject, writer):
writer.simpletag("advance", height=repr(height))
writer.newline()
def _writeUnicodes(glyphObject, writer):
def _writeUnicodes(glyphObject, writer, validate):
unicodes = getattr(glyphObject, "unicodes", None)
if isinstance(unicodes, int):
if validate and isinstance(unicodes, int):
unicodes = [unicodes]
seen = set()
for code in unicodes:
if not isinstance(code, int):
if validate and not isinstance(code, int):
raise GlifLibError("unicode values must be int")
if code in seen:
continue
@ -674,9 +674,9 @@ def _writeUnicodes(glyphObject, writer):
writer.simpletag("unicode", hex=hexCode)
writer.newline()
def _writeNote(glyphObject, writer):
def _writeNote(glyphObject, writer, validate):
note = getattr(glyphObject, "note", None)
if not isinstance(note, basestring):
if validate and not isinstance(note, basestring):
raise GlifLibError("note attribute must be str or unicode")
note = note.encode("utf-8")
writer.begintag("note")
@ -727,7 +727,7 @@ def _writeGuidelines(glyphObject, writer, identifiers, validate):
attrs.append(("color", color))
identifier = guideline.get("identifier")
if identifier is not None:
if identifier in identifiers:
if validate and identifier in identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
attrs.append(("identifier", identifier))
identifiers.add(identifier)
@ -768,7 +768,7 @@ def _writeAnchors(glyphObject, writer, identifiers, validate):
attrs.append(("color", color))
identifier = anchor.get("identifier")
if identifier is not None:
if identifier in identifiers:
if validate and identifier in identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
attrs.append(("identifier", identifier))
identifiers.add(identifier)
@ -868,14 +868,14 @@ def _glifTreeFromString(aString):
def _readGlyphFromTree(tree, glyphObject=None, pointPen=None, formatVersions=(1, 2), validate=False):
# check the format version
formatVersion = tree.get("format")
if formatVersion is None:
if validate and formatVersion is None:
raise GlifLibError("Unspecified format version in GLIF.")
try:
v = int(formatVersion)
formatVersion = v
except ValueError:
pass
if formatVersion not in formatVersions:
if validate and formatVersion not in formatVersions:
raise GlifLibError("Forbidden GLIF format version: %s" % formatVersion)
if formatVersion == 1:
_readGlyphFromTreeFormat1(tree=tree, glyphObject=glyphObject, pointPen=pointPen, validate=validate)
@ -887,24 +887,25 @@ def _readGlyphFromTree(tree, glyphObject=None, pointPen=None, formatVersions=(1,
def _readGlyphFromTreeFormat1(tree, glyphObject=None, pointPen=None, validate=None):
# get the name
_readName(glyphObject, tree)
_readName(glyphObject, tree, validate)
# populate the sub elements
unicodes = []
haveSeenAdvance = haveSeenOutline = haveSeenLib = haveSeenNote = False
for element in tree:
if element.tag == "outline":
if haveSeenOutline:
raise GlifLibError("The outline element occurs more than once.")
if element.attrib:
raise GlifLibError("The outline element contains unknown attributes.")
if element.text and element.text.strip() != '':
raise GlifLibError("Invalid outline structure.")
if validate:
if haveSeenOutline:
raise GlifLibError("The outline element occurs more than once.")
if element.attrib:
raise GlifLibError("The outline element contains unknown attributes.")
if element.text and element.text.strip() != '':
raise GlifLibError("Invalid outline structure.")
haveSeenOutline = True
buildOutlineFormat1(glyphObject, pointPen, element, validate)
elif glyphObject is None:
continue
elif element.tag == "advance":
if haveSeenAdvance:
if validate and haveSeenAdvance:
raise GlifLibError("The advance element occurs more than once.")
haveSeenAdvance = True
_readAdvance(glyphObject, element)
@ -917,12 +918,12 @@ def _readGlyphFromTreeFormat1(tree, glyphObject=None, pointPen=None, validate=No
except ValueError:
raise GlifLibError("Illegal value for hex attribute of unicode element.")
elif element.tag == "note":
if haveSeenNote:
if validate and haveSeenNote:
raise GlifLibError("The note element occurs more than once.")
haveSeenNote = True
_readNote(glyphObject, element)
elif element.tag == "lib":
if haveSeenLib:
if validate and haveSeenLib:
raise GlifLibError("The lib element occurs more than once.")
haveSeenLib = True
_readLib(glyphObject, element, validate)
@ -934,7 +935,7 @@ def _readGlyphFromTreeFormat1(tree, glyphObject=None, pointPen=None, validate=No
def _readGlyphFromTreeFormat2(tree, glyphObject=None, pointPen=None, validate=None):
# get the name
_readName(glyphObject, tree)
_readName(glyphObject, tree, validate)
# populate the sub elements
unicodes = []
guidelines = []
@ -943,19 +944,20 @@ def _readGlyphFromTreeFormat2(tree, glyphObject=None, pointPen=None, validate=No
identifiers = set()
for element in tree:
if element.tag == "outline":
if haveSeenOutline:
raise GlifLibError("The outline element occurs more than once.")
if element.attrib:
raise GlifLibError("The outline element contains unknown attributes.")
if element.text and element.text.strip() != '':
raise GlifLibError("Invalid outline structure.")
if validate:
if haveSeenOutline:
raise GlifLibError("The outline element occurs more than once.")
if element.attrib:
raise GlifLibError("The outline element contains unknown attributes.")
if element.text and element.text.strip() != '':
raise GlifLibError("Invalid outline structure.")
haveSeenOutline = True
if pointPen is not None:
buildOutlineFormat2(glyphObject, pointPen, element, identifiers, validate)
elif glyphObject is None:
continue
elif element.tag == "advance":
if haveSeenAdvance:
if validate and haveSeenAdvance:
raise GlifLibError("The advance element occurs more than once.")
haveSeenAdvance = True
_readAdvance(glyphObject, element)
@ -968,33 +970,34 @@ def _readGlyphFromTreeFormat2(tree, glyphObject=None, pointPen=None, validate=No
except ValueError:
raise GlifLibError("Illegal value for hex attribute of unicode element.")
elif element.tag == "guideline":
if len(element):
if validate and len(element):
raise GlifLibError("Unknown children in guideline element.")
for attr in ("x", "y", "angle"):
if attr in element.attrib:
element.attrib[attr] = _number(element.attrib[attr])
guidelines.append(element.attrib)
elif element.tag == "anchor":
if len(element):
if validate and len(element):
raise GlifLibError("Unknown children in anchor element.")
for attr in ("x", "y"):
if attr in element.attrib:
element.attrib[attr] = _number(element.attrib[attr])
anchors.append(element.attrib)
elif element.tag == "image":
if haveSeenImage:
raise GlifLibError("The image element occurs more than once.")
if len(element):
raise GlifLibError("Unknown children in image element.")
if validate:
if haveSeenImage:
raise GlifLibError("The image element occurs more than once.")
if len(element):
raise GlifLibError("Unknown children in image element.")
haveSeenImage = True
_readImage(glyphObject, element, validate)
elif element.tag == "note":
if haveSeenNote:
if validate and haveSeenNote:
raise GlifLibError("The note element occurs more than once.")
haveSeenNote = True
_readNote(glyphObject, element)
elif element.tag == "lib":
if haveSeenLib:
if validate and haveSeenLib:
raise GlifLibError("The lib element occurs more than once.")
haveSeenLib = True
_readLib(glyphObject, element, validate)
@ -1005,18 +1008,18 @@ def _readGlyphFromTreeFormat2(tree, glyphObject=None, pointPen=None, validate=No
_relaxedSetattr(glyphObject, "unicodes", unicodes)
# set the collected guidelines
if guidelines:
if not guidelinesValidator(guidelines, identifiers):
if validate and not guidelinesValidator(guidelines, identifiers):
raise GlifLibError("The guidelines are improperly formatted.")
_relaxedSetattr(glyphObject, "guidelines", guidelines)
# set the collected anchors
if anchors:
if not anchorsValidator(anchors, identifiers):
if validate and not anchorsValidator(anchors, identifiers):
raise GlifLibError("The anchors are improperly formatted.")
_relaxedSetattr(glyphObject, "anchors", anchors)
def _readName(glyphObject, root):
def _readName(glyphObject, root, validate):
glyphName = root.get("name")
if not glyphName:
if validate and not glyphName:
raise GlifLibError("Empty glyph name in GLIF.")
if glyphName and glyphObject is not None:
_relaxedSetattr(glyphObject, "name", glyphName)
@ -1072,7 +1075,7 @@ def buildOutlineFormat1(glyphObject, pen, outline, validate):
if len(element) == 1:
point = element[0]
if point.tag == "point":
anchor = _buildAnchorFormat1(point)
anchor = _buildAnchorFormat1(point, validate)
if anchor is not None:
anchors.append(anchor)
continue
@ -1080,7 +1083,7 @@ def buildOutlineFormat1(glyphObject, pen, outline, validate):
_buildOutlineContourFormat1(pen, element, validate)
elif element.tag == "component":
if pen is not None:
_buildOutlineComponentFormat1(pen, element)
_buildOutlineComponentFormat1(pen, element, validate)
else:
raise GlifLibError("Unknown element in outline element: %s" % element)
if glyphObject is not None and anchors:
@ -1088,7 +1091,7 @@ def buildOutlineFormat1(glyphObject, pen, outline, validate):
raise GlifLibError("GLIF 1 anchors are not properly formatted.")
_relaxedSetattr(glyphObject, "anchors", anchors)
def _buildAnchorFormat1(point):
def _buildAnchorFormat1(point, validate):
if point.get("type") != "move":
return None
name = point.get("name")
@ -1096,9 +1099,9 @@ def _buildAnchorFormat1(point):
return None
x = point.get("x")
y = point.get("y")
if x is None:
if validate and x is None:
raise GlifLibError("Required x attribute is missing in point element.")
if y is None:
if validate and y is None:
raise GlifLibError("Required y attribute is missing in point element.")
x = _number(x)
y = _number(y)
@ -1106,7 +1109,7 @@ def _buildAnchorFormat1(point):
return anchor
def _buildOutlineContourFormat1(pen, contour, validate):
if contour.attrib:
if validate and contour.attrib:
raise GlifLibError("Unknown attributes in contour element.")
pen.beginPath()
if len(contour):
@ -1123,14 +1126,15 @@ def _buildOutlinePointsFormat1(pen, contour):
name = element.attrib["name"]
pen.addPoint((x, y), segmentType=segmentType, smooth=smooth, name=name)
def _buildOutlineComponentFormat1(pen, component):
if len(component):
raise GlifLibError("Unknown child elements of component element.")
for attr in component.attrib.keys():
if attr not in componentAttributesFormat1:
raise GlifLibError("Unknown attribute in component element: %s" % attr)
def _buildOutlineComponentFormat1(pen, component, validate):
if validate:
if len(component):
raise GlifLibError("Unknown child elements of component element.")
for attr in component.attrib.keys():
if attr not in componentAttributesFormat1:
raise GlifLibError("Unknown attribute in component element: %s" % attr)
baseGlyphName = component.get("base")
if baseGlyphName is None:
if validate and baseGlyphName is None:
raise GlifLibError("The base attribute is not defined in the component.")
transformation = []
for attr, default in _transformationInfo:
@ -1154,15 +1158,17 @@ def buildOutlineFormat2(glyphObject, pen, outline, identifiers, validate):
raise GlifLibError("Unknown element in outline element: %s" % element.tag)
def _buildOutlineContourFormat2(pen, contour, identifiers, validate):
for attr in contour.attrib.keys():
if attr not in contourAttributesFormat2:
raise GlifLibError("Unknown attribute in contour element: %s" % attr)
if validate:
for attr in contour.attrib.keys():
if attr not in contourAttributesFormat2:
raise GlifLibError("Unknown attribute in contour element: %s" % attr)
identifier = contour.get("identifier")
if identifier is not None:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if validate and not identifierValidator(identifier):
raise GlifLibError("The contour identifier %s is not valid." % identifier)
if validate:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if not identifierValidator(identifier):
raise GlifLibError("The contour identifier %s is not valid." % identifier)
identifiers.add(identifier)
try:
pen.beginPath(identifier=identifier)
@ -1183,10 +1189,11 @@ def _buildOutlinePointsFormat2(pen, contour, identifiers, validate):
name = element.attrib["name"]
identifier = element.get("identifier")
if identifier is not None:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if validate and not identifierValidator(identifier):
raise GlifLibError("The identifier %s is not valid." % identifier)
if validate:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if not identifierValidator(identifier):
raise GlifLibError("The identifier %s is not valid." % identifier)
identifiers.add(identifier)
try:
pen.addPoint((x, y), segmentType=segmentType, smooth=smooth, name=name, identifier=identifier)
@ -1195,13 +1202,14 @@ def _buildOutlinePointsFormat2(pen, contour, identifiers, validate):
warn("The addPoint method needs an identifier kwarg. The point's identifier value has been discarded.", DeprecationWarning)
def _buildOutlineComponentFormat2(pen, component, identifiers, validate):
if len(component):
raise GlifLibError("Unknown child elements of component element.")
for attr in component.attrib.keys():
if attr not in componentAttributesFormat2:
raise GlifLibError("Unknown attribute in component element: %s" % attr)
if validate:
if len(component):
raise GlifLibError("Unknown child elements of component element.")
for attr in component.attrib.keys():
if attr not in componentAttributesFormat2:
raise GlifLibError("Unknown attribute in component element: %s" % attr)
baseGlyphName = component.get("base")
if baseGlyphName is None:
if validate and baseGlyphName is None:
raise GlifLibError("The base attribute is not defined in the component.")
transformation = []
for attr, default in _transformationInfo:
@ -1213,10 +1221,11 @@ def _buildOutlineComponentFormat2(pen, component, identifiers, validate):
transformation.append(value)
identifier = component.get("identifier")
if identifier is not None:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if validate and not identifierValidator(identifier):
raise GlifLibError("The identifier %s is not valid." % identifier)
if validate:
if identifier in identifiers:
raise GlifLibError("The identifier %s is used more than once." % identifier)
if validate and not identifierValidator(identifier):
raise GlifLibError("The identifier %s is not valid." % identifier)
identifiers.add(identifier)
try:
pen.addComponent(baseGlyphName, tuple(transformation), identifier=identifier)
@ -1496,10 +1505,11 @@ class GLIFPointPen(AbstractPointPen):
def beginPath(self, identifier=None, **kwargs):
attrs = []
if identifier is not None and self.formatVersion >= 2:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if self.validate and not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
if self.validate:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
attrs.append(("identifier", identifier))
self.identifiers.add(identifier)
self.writer.begintag("contour", attrs)
@ -1508,7 +1518,7 @@ class GLIFPointPen(AbstractPointPen):
def endPath(self):
if self.prevPointTypes and self.prevPointTypes[0] == "move":
if self.prevPointTypes[-1] == "offcurve":
if self.validate and self.prevPointTypes[-1] == "offcurve":
raise GlifLibError("open contour has loose offcurve point")
self.writer.endtag("contour")
self.writer.newline()
@ -1520,20 +1530,22 @@ class GLIFPointPen(AbstractPointPen):
attrs = []
# coordinates
if pt is not None:
for coord in pt:
if not isinstance(coord, (int, float)):
raise GlifLibError("coordinates must be int or float")
if self.validate:
for coord in pt:
if not isinstance(coord, (int, float)):
raise GlifLibError("coordinates must be int or float")
attrs.append(("x", repr(pt[0])))
attrs.append(("y", repr(pt[1])))
# segment type
if segmentType == "offcurve":
segmentType = None
if segmentType == "move" and self.prevPointTypes:
raise GlifLibError("move occurs after a point has already been added to the contour.")
if segmentType in ("move", "line") and self.prevPointTypes and self.prevPointTypes[-1] == "offcurve":
raise GlifLibError("offcurve occurs before %s point." % segmentType)
if segmentType == "curve" and self.prevOffCurveCount > 2:
raise GlifLibError("too many offcurve points before curve point.")
if self.validate:
if segmentType == "move" and self.prevPointTypes:
raise GlifLibError("move occurs after a point has already been added to the contour.")
if segmentType in ("move", "line") and self.prevPointTypes and self.prevPointTypes[-1] == "offcurve":
raise GlifLibError("offcurve occurs before %s point." % segmentType)
if segmentType == "curve" and self.prevOffCurveCount > 2:
raise GlifLibError("too many offcurve points before curve point.")
if segmentType is not None:
attrs.append(("type", segmentType))
else:
@ -1545,7 +1557,7 @@ class GLIFPointPen(AbstractPointPen):
self.prevPointTypes.append(segmentType)
# smooth
if smooth:
if segmentType == "offcurve":
if self.validate and segmentType == "offcurve":
raise GlifLibError("can't set smooth in an offcurve point.")
attrs.append(("smooth", "yes"))
# name
@ -1553,10 +1565,11 @@ class GLIFPointPen(AbstractPointPen):
attrs.append(("name", name))
# identifier
if identifier is not None and self.formatVersion >= 2:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if self.validate and not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
if self.validate:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
attrs.append(("identifier", identifier))
self.identifiers.add(identifier)
self.writer.simpletag("point", attrs)
@ -1565,15 +1578,16 @@ class GLIFPointPen(AbstractPointPen):
def addComponent(self, glyphName, transformation, identifier=None, **kwargs):
attrs = [("base", glyphName)]
for (attr, default), value in zip(_transformationInfo, transformation):
if not isinstance(value, (int, float)):
if self.validate and not isinstance(value, (int, float)):
raise GlifLibError("transformation values must be int or float")
if value != default:
attrs.append((attr, repr(value)))
if identifier is not None and self.formatVersion >= 2:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if self.validate and not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
if self.validate:
if identifier in self.identifiers:
raise GlifLibError("identifier used more than once: %s" % identifier)
if self.validate and not identifierValidator(identifier):
raise GlifLibError("identifier not formatted properly: %s" % identifier)
attrs.append(("identifier", identifier))
self.identifiers.add(identifier)
self.writer.simpletag("component", attrs)

View File

@ -24,7 +24,7 @@ class TestGLIF1(unittest.TestCase):
py = stripText(py)
glyph = Glyph()
exec(py, {"glyph" : glyph, "pointPen" : glyph})
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=1)
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=1, validate=True)
glif = "\n".join(glif.splitlines()[1:])
return glif
@ -32,7 +32,7 @@ class TestGLIF1(unittest.TestCase):
glif = stripText(glif)
glif = "<?xml version=\"1.0\" encoding=\"UTF-8\"?>\n" + glif
glyph = Glyph()
readGlyphFromString(glif, glyphObject=glyph, pointPen=glyph)
readGlyphFromString(glif, glyphObject=glyph, pointPen=glyph, validate=True)
return glyph.py()
def testTopElement(self):

View File

@ -24,7 +24,7 @@ class TestGLIF2(unittest.TestCase):
py = stripText(py)
glyph = Glyph()
exec(py, {"glyph" : glyph, "pointPen" : glyph})
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=2)
glif = writeGlyphToString(glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, formatVersion=2, validate=True)
glif = "\n".join(glif.splitlines()[1:])
return glif