# Conflicts:
#	Lib/designSpaceDocument/__init__.py
This commit is contained in:
Erik 2016-11-20 10:14:25 +01:00
commit 079771dd76
2 changed files with 62 additions and 52 deletions

4
.gitignore vendored
View File

@ -1,2 +1,6 @@
test.designspace test.designspace
Lib/DesignSpaceDocument.egg-info Lib/DesignSpaceDocument.egg-info
.cache
__pycache__
*.py[co]
.DS_Store

View File

@ -1,5 +1,6 @@
# -*- coding: utf-8 -*- # -*- coding: utf-8 -*-
from __future__ import print_function, unicode_literals
import os import os
import xml.etree.ElementTree as ET import xml.etree.ElementTree as ET
@ -19,13 +20,16 @@ __all__ = [
'SourceDescriptor', 'InstanceDescriptor', 'SourceDescriptor', 'InstanceDescriptor',
'AxisDescriptor', 'BaseDocReader', 'BaseDocWriter'] 'AxisDescriptor', 'BaseDocReader', 'BaseDocWriter']
class DesignSpaceDocumentError(Exception): class DesignSpaceDocumentError(Exception):
def __init__(self, msg, obj=None): def __init__(self, msg, obj=None):
self.msg = msg self.msg = msg
self.obj = obj self.obj = obj
def __str__(self): def __str__(self):
return repr(self.msg) + repr(self.obj) return repr(self.msg) + repr(self.obj)
def _indent(elem, whitespace=" ", level=0): def _indent(elem, whitespace=" ", level=0):
# taken from http://effbot.org/zone/element-lib.htm#prettyprint # taken from http://effbot.org/zone/element-lib.htm#prettyprint
i = "\n" + level * whitespace i = "\n" + level * whitespace
@ -42,26 +46,28 @@ def _indent(elem, whitespace=" ", level=0):
if level and (not elem.tail or not elem.tail.strip()): if level and (not elem.tail or not elem.tail.strip()):
elem.tail = i elem.tail = i
class SimpleDescriptor(object): class SimpleDescriptor(object):
""" Containers for a bunch of attributes""" """ Containers for a bunch of attributes"""
def compare(self, other): def compare(self, other):
# test if this object contains the same data as the other # test if this object contains the same data as the other
for attr in self._attrs: for attr in self._attrs:
try: try:
#print getattr(self, attr), getattr(other, attr) assert(getattr(self, attr) == getattr(other, attr))
assert(getattr(self,attr) == getattr(other,attr))
except AssertionError: except AssertionError:
print "failed attribute", attr, getattr(self, attr), "!=", getattr(other, attr) print("failed attribute", attr, getattr(self, attr), "!=", getattr(other, attr))
class SourceDescriptor(SimpleDescriptor): class SourceDescriptor(SimpleDescriptor):
"""Simple container for data related to the source""" """Simple container for data related to the source"""
flavor="source" flavor = "source"
_attrs = [ 'path', 'name', _attrs = ['path', 'name',
'location', 'copyLib', 'location', 'copyLib',
'copyGroups', 'copyFeatures', 'copyGroups', 'copyFeatures',
'muteKerning', 'muteInfo', 'muteKerning', 'muteInfo',
'mutedGlyphNames', 'mutedGlyphNames',
'familyName', 'styleName'] 'familyName', 'styleName']
def __init__(self): def __init__(self):
self.path = None self.path = None
self.name = None self.name = None
@ -79,13 +85,14 @@ class SourceDescriptor(SimpleDescriptor):
class InstanceDescriptor(SimpleDescriptor): class InstanceDescriptor(SimpleDescriptor):
"""Simple container for data related to the instance""" """Simple container for data related to the instance"""
flavor="instance" flavor = "instance"
_attrs = [ 'path', 'name', _attrs = ['path', 'name',
'location', 'familyName', 'location', 'familyName',
'styleName', 'postScriptFontName', 'styleName', 'postScriptFontName',
'styleMapFamilyName', 'styleMapFamilyName',
'styleMapStyleName', 'styleMapStyleName',
'kerning', 'info'] 'kerning', 'info']
def __init__(self): def __init__(self):
self.path = None self.path = None
self.name = None self.name = None
@ -102,19 +109,20 @@ class InstanceDescriptor(SimpleDescriptor):
class AxisDescriptor(SimpleDescriptor): class AxisDescriptor(SimpleDescriptor):
"""Simple container for the axis data""" """Simple container for the axis data"""
flavor="axis" flavor = "axis"
_attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map'] _attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map']
def __init__(self): def __init__(self):
self.tag = None # opentype tag for this axis self.tag = None # opentype tag for this axis
self.name = None # name of the axis used in locations self.name = None # name of the axis used in locations
self.labelNames = {} # names for UI purposes, if this is not a standard axis, self.labelNames = {} # names for UI purposes, if this is not a standard axis,
self.minimum = None self.minimum = None
self.maximum = None self.maximum = None
self.default = None self.default = None
self.map = [] self.map = []
def serialize(self): def serialize(self):
# output to a dict # output to a dict, used in testing
d = dict(tag = self.tag, d = dict(tag = self.tag,
name = self.name, name = self.name,
labelNames = self.labelNames, labelNames = self.labelNames,
@ -131,12 +139,13 @@ class BaseDocWriter(object):
axisDescriptorClass = AxisDescriptor axisDescriptorClass = AxisDescriptor
sourceDescriptorClass = SourceDescriptor sourceDescriptorClass = SourceDescriptor
instanceDescriptorClass = InstanceDescriptor instanceDescriptorClass = InstanceDescriptor
def __init__(self, documentPath, documentObject): def __init__(self, documentPath, documentObject):
self.path = documentPath self.path = documentPath
self.documentObject = documentObject self.documentObject = documentObject
self.toolVersion = 3 self.toolVersion = 3
self.root = ET.Element("designspace") self.root = ET.Element("designspace")
self.root.attrib['format'] = "%d"%self.toolVersion self.root.attrib['format'] = "%d" % self.toolVersion
self.root.append(ET.Element("axes")) self.root.append(ET.Element("axes"))
self.root.append(ET.Element("sources")) self.root.append(ET.Element("sources"))
self.root.append(ET.Element("instances")) self.root.append(ET.Element("instances"))
@ -158,13 +167,13 @@ class BaseDocWriter(object):
if pretty: if pretty:
_indent(self.root, whitespace=self._whiteSpace) _indent(self.root, whitespace=self._whiteSpace)
tree = ET.ElementTree(self.root) tree = ET.ElementTree(self.root)
tree.write(self.path, encoding=u"utf-8", method='xml', xml_declaration=True) tree.write(self.path, encoding="utf-8", method='xml', xml_declaration=True)
def _makeLocationElement(self, locationObject, name=None): def _makeLocationElement(self, locationObject, name=None):
""" Convert Location dict to a locationElement.""" """ Convert Location dict to a locationElement."""
locElement = ET.Element("location") locElement = ET.Element("location")
if name is not None: if name is not None:
locElement.attrib['name'] = name locElement.attrib['name'] = name
defaultLoc = self.newDefaultLocation() defaultLoc = self.newDefaultLocation()
validatedLocation = {} validatedLocation = {}
for axisName, axisValue in defaultLoc.items(): for axisName, axisValue in defaultLoc.items():
@ -174,20 +183,20 @@ class BaseDocWriter(object):
else: else:
validatedLocation[axisName] = locationObject[axisName] validatedLocation[axisName] = locationObject[axisName]
for dimensionName, dimensionValue in validatedLocation.items(): for dimensionName, dimensionValue in validatedLocation.items():
dimElement = ET.Element('dimension') dimElement = ET.Element('dimension')
dimElement.attrib['name'] = dimensionName dimElement.attrib['name'] = dimensionName
if type(dimensionValue)==tuple: if type(dimensionValue) == tuple:
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue[0]) dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue[0])
dimElement.attrib['yvalue'] = self.intOrFloat(dimensionValue[1]) dimElement.attrib['yvalue'] = self.intOrFloat(dimensionValue[1])
else: else:
dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue) dimElement.attrib['xvalue'] = self.intOrFloat(dimensionValue)
locElement.append(dimElement) locElement.append(dimElement)
return locElement, validatedLocation return locElement, validatedLocation
def intOrFloat(self, num): def intOrFloat(self, num):
if int(num) == num: if int(num) == num:
return "%d"%num return "%d" % num
return "%f"%num return "%f" % num
def _addAxis(self, axisObject): def _addAxis(self, axisObject):
self.axes.append(axisObject) self.axes.append(axisObject)
@ -319,10 +328,12 @@ class BaseDocWriter(object):
glyphElement.append(mastersElement) glyphElement.append(mastersElement)
return glyphElement return glyphElement
class BaseDocReader(object): class BaseDocReader(object):
axisDescriptorClass = AxisDescriptor axisDescriptorClass = AxisDescriptor
sourceDescriptorClass = SourceDescriptor sourceDescriptorClass = SourceDescriptor
instanceDescriptorClass = InstanceDescriptor instanceDescriptorClass = InstanceDescriptor
def __init__(self, documentPath, documentObject): def __init__(self, documentPath, documentObject):
self.path = documentPath self.path = documentPath
self.documentObject = documentObject self.documentObject = documentObject
@ -566,9 +577,9 @@ class BaseDocReader(object):
if masterGlyphName is None: if masterGlyphName is None:
# if we don't read a glyphname, use the one we have # if we don't read a glyphname, use the one we have
masterGlyphName = glyphName masterGlyphName = glyphName
d = dict( font=fontSourceName, d = dict(font=fontSourceName,
location=sourceLocation, location=sourceLocation,
glyphName=masterGlyphName) glyphName=masterGlyphName)
if glyphSources is None: if glyphSources is None:
glyphSources = [] glyphSources = []
glyphSources.append(d) glyphSources.append(d)
@ -620,14 +631,10 @@ class DesignSpaceDocument(object):
return loc return loc
if __name__ == "__main__": if __name__ == "__main__":
def test(): def test():
u""" """
>>> import os >>> import os
>>> testDocPath = os.path.join(os.getcwd(), "test.designspace") >>> testDocPath = os.path.join(os.getcwd(), "test.designspace")
>>> masterPath1 = os.path.join(os.getcwd(), "masters", "masterTest1.ufo") >>> masterPath1 = os.path.join(os.getcwd(), "masters", "masterTest1.ufo")
@ -753,5 +760,4 @@ if __name__ == "__main__":
def _test(): def _test():
import doctest import doctest
doctest.testmod() doctest.testmod()
_test() _test()