WIP axes are compulsory, so don't accomodate missing axes. Raise error if document is missing axes.
We know what the default location is before we start reading the masters and there is no guessing. findDefault() method: default master is at all default values of all axes, or if that fails, the master with the copyInfo flag. Warn if a location contains an axis that is not defined in the axes element. Otherwise ignore this value, no guessing. Remove rulesToFeature() function.
This commit is contained in:
parent
bbd1ba64b2
commit
086de222fa
@ -6,18 +6,17 @@ import logging
|
|||||||
import os
|
import os
|
||||||
import posixpath
|
import posixpath
|
||||||
import plistlib
|
import plistlib
|
||||||
|
import warnings
|
||||||
|
|
||||||
try:
|
try:
|
||||||
import xml.etree.cElementTree as ET
|
import xml.etree.cElementTree as ET
|
||||||
except ImportError:
|
except ImportError:
|
||||||
import xml.etree.ElementTree as ET
|
import xml.etree.ElementTree as ET
|
||||||
# from mutatorMath.objects.location import biasFromLocations, Location
|
|
||||||
|
|
||||||
"""
|
"""
|
||||||
designSpaceDocument
|
designSpaceDocument
|
||||||
|
|
||||||
- read and write designspace files
|
- read and write designspace files
|
||||||
- axes must be defined.
|
|
||||||
- warpmap is stored in its axis element
|
|
||||||
"""
|
"""
|
||||||
|
|
||||||
__all__ = [
|
__all__ = [
|
||||||
@ -726,8 +725,7 @@ class BaseDocReader(object):
|
|||||||
# read the axes elements, including the warp map.
|
# read the axes elements, including the warp map.
|
||||||
axes = []
|
axes = []
|
||||||
if len(self.root.findall(".axes/axis"))==0:
|
if len(self.root.findall(".axes/axis"))==0:
|
||||||
self.guessAxes()
|
raise DesignSpaceDocumentError("No axes defined.")
|
||||||
self._strictAxisNames = False
|
|
||||||
return
|
return
|
||||||
for axisElement in self.root.findall(".axes/axis"):
|
for axisElement in self.root.findall(".axes/axis"):
|
||||||
axisObject = self.axisDescriptorClass()
|
axisObject = self.axisDescriptorClass()
|
||||||
@ -750,10 +748,13 @@ class BaseDocReader(object):
|
|||||||
axisObject.labelNames[lang] = labelName
|
axisObject.labelNames[lang] = labelName
|
||||||
self.documentObject.axes.append(axisObject)
|
self.documentObject.axes.append(axisObject)
|
||||||
self.axisDefaults[axisObject.name] = axisObject.default
|
self.axisDefaults[axisObject.name] = axisObject.default
|
||||||
|
self.documentObject.defaultLoc = self.axisDefaults
|
||||||
|
|
||||||
def _locationFromElement(self, locationElement):
|
def _locationFromElement(self, locationElement):
|
||||||
# mostly duplicated from readLocationElement, Needs Resolve.
|
# mostly duplicated from readLocationElement, Needs Resolve.
|
||||||
loc = {}
|
loc = {}
|
||||||
|
# make sure all locations start with the defaults
|
||||||
|
loc.update(self.axisDefaults)
|
||||||
for dimensionElement in locationElement.findall(".dimension"):
|
for dimensionElement in locationElement.findall(".dimension"):
|
||||||
dimName = dimensionElement.attrib.get("name")
|
dimName = dimensionElement.attrib.get("name")
|
||||||
xValue = yValue = None
|
xValue = yValue = None
|
||||||
@ -774,42 +775,42 @@ class BaseDocReader(object):
|
|||||||
loc[dimName] = xValue
|
loc[dimName] = xValue
|
||||||
return loc
|
return loc
|
||||||
|
|
||||||
def guessAxes(self):
|
# def guessAxes(self):
|
||||||
# Called when we have no axes element in the file.
|
# # Called when we have no axes element in the file.
|
||||||
# Look at all locations and collect the axis names and values
|
# # Look at all locations and collect the axis names and values
|
||||||
# assumptions:
|
# # assumptions:
|
||||||
# look for the default value on an axis from a master location
|
# # look for the default value on an axis from a master location
|
||||||
# Needs deprecation warning
|
# # Needs deprecation warning
|
||||||
allLocations = []
|
# allLocations = []
|
||||||
minima = {}
|
# minima = {}
|
||||||
maxima = {}
|
# maxima = {}
|
||||||
for locationElement in self.root.findall(".sources/source/location"):
|
# for locationElement in self.root.findall(".sources/source/location"):
|
||||||
allLocations.append(self._locationFromElement(locationElement))
|
# allLocations.append(self._locationFromElement(locationElement))
|
||||||
for locationElement in self.root.findall(".instances/instance/location"):
|
# for locationElement in self.root.findall(".instances/instance/location"):
|
||||||
allLocations.append(self._locationFromElement(locationElement))
|
# allLocations.append(self._locationFromElement(locationElement))
|
||||||
for loc in allLocations:
|
# for loc in allLocations:
|
||||||
for dimName, value in loc.items():
|
# for dimName, value in loc.items():
|
||||||
if not isinstance(value, tuple):
|
# if not isinstance(value, tuple):
|
||||||
value = [value]
|
# value = [value]
|
||||||
for v in value:
|
# for v in value:
|
||||||
if dimName not in minima:
|
# if dimName not in minima:
|
||||||
minima[dimName] = v
|
# minima[dimName] = v
|
||||||
continue
|
# continue
|
||||||
if minima[dimName] > v:
|
# if minima[dimName] > v:
|
||||||
minima[dimName] = v
|
# minima[dimName] = v
|
||||||
if dimName not in maxima:
|
# if dimName not in maxima:
|
||||||
maxima[dimName] = v
|
# maxima[dimName] = v
|
||||||
continue
|
# continue
|
||||||
if maxima[dimName] < v:
|
# if maxima[dimName] < v:
|
||||||
maxima[dimName] = v
|
# maxima[dimName] = v
|
||||||
newAxes = []
|
# newAxes = []
|
||||||
for axisName in maxima.keys():
|
# for axisName in maxima.keys():
|
||||||
a = self.axisDescriptorClass()
|
# a = self.axisDescriptorClass()
|
||||||
a.default = a.minimum = minima[axisName]
|
# a.default = a.minimum = minima[axisName]
|
||||||
a.maximum = maxima[axisName]
|
# a.maximum = maxima[axisName]
|
||||||
a.name = axisName
|
# a.name = axisName
|
||||||
a.tag, a.labelNames = tagForAxisName(axisName)
|
# a.tag, a.labelNames = tagForAxisName(axisName)
|
||||||
self.documentObject.axes.append(a)
|
# self.documentObject.axes.append(a)
|
||||||
|
|
||||||
def readSources(self):
|
def readSources(self):
|
||||||
for sourceCount, sourceElement in enumerate(self.root.findall(".sources/source")):
|
for sourceCount, sourceElement in enumerate(self.root.findall(".sources/source")):
|
||||||
@ -874,10 +875,8 @@ class BaseDocReader(object):
|
|||||||
for dimensionElement in locationElement.findall(".dimension"):
|
for dimensionElement in locationElement.findall(".dimension"):
|
||||||
dimName = dimensionElement.attrib.get("name")
|
dimName = dimensionElement.attrib.get("name")
|
||||||
if self._strictAxisNames and dimName not in self.axisDefaults:
|
if self._strictAxisNames and dimName not in self.axisDefaults:
|
||||||
# In case the document contains axis definitions,
|
# In case the document contains no axis definitions,
|
||||||
# then we should only read the axes we know about.
|
warnings.warn("Location with undefined axis: \"%s\"." % dimName)
|
||||||
# However, if the document does not contain axes,
|
|
||||||
# then we need to create them after reading.
|
|
||||||
continue
|
continue
|
||||||
xValue = yValue = None
|
xValue = yValue = None
|
||||||
try:
|
try:
|
||||||
@ -1094,6 +1093,7 @@ class DesignSpaceDocument(object):
|
|||||||
self.filename = os.path.basename(path)
|
self.filename = os.path.basename(path)
|
||||||
reader = self.readerClass(path, self)
|
reader = self.readerClass(path, self)
|
||||||
reader.read()
|
reader.read()
|
||||||
|
self.findDefault()
|
||||||
|
|
||||||
def write(self, path):
|
def write(self, path):
|
||||||
self.path = path
|
self.path = path
|
||||||
@ -1222,78 +1222,23 @@ class DesignSpaceDocument(object):
|
|||||||
return axisDescriptor
|
return axisDescriptor
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def check(self):
|
def findDefault(self):
|
||||||
"""
|
# new default finder
|
||||||
After reading we need to make sure we have a valid designspace.
|
# take the master with the location at all the defaults
|
||||||
This means making repairs if things are missing
|
self.default = None
|
||||||
- check if we have axes and deduce them from the masters if they're missing
|
for sourceDescriptor in self.sources:
|
||||||
- that can include axes referenced in masters, instances, glyphs.
|
if sourceDescriptor.location == self.defaultLoc:
|
||||||
- if no default is assigned, use mutatormath to find out.
|
# we choose you!
|
||||||
- record the default in the designspace
|
self.default = sourceDescriptor
|
||||||
- report all the changes in a log
|
return sourceDescriptor
|
||||||
- save a "repaired" version of the doc
|
# failing that, tkae the master with the copyInfo flag
|
||||||
"""
|
|
||||||
self.checkAxes()
|
|
||||||
self.checkDefault()
|
|
||||||
|
|
||||||
def checkDefault(self):
|
|
||||||
""" Check the sources for a copyInfo flag."""
|
|
||||||
flaggedDefaultCandidate = None
|
|
||||||
for sourceDescriptor in self.sources:
|
for sourceDescriptor in self.sources:
|
||||||
names = set()
|
names = set()
|
||||||
if sourceDescriptor.copyInfo:
|
if sourceDescriptor.copyInfo:
|
||||||
# we choose you!
|
# we choose you!
|
||||||
flaggedDefaultCandidate = sourceDescriptor
|
self.default = sourceDescriptor
|
||||||
mutatorDefaultCandidate = self.getMutatorDefaultCandidate()
|
return sourceDescriptor
|
||||||
# what are we going to do?
|
# failing that, well, fail. We don't want to guess any more.
|
||||||
if flaggedDefaultCandidate is not None:
|
|
||||||
if mutatorDefaultCandidate is not None:
|
|
||||||
if mutatorDefaultCandidate.name != flaggedDefaultCandidate.name:
|
|
||||||
# warn if we have a conflict
|
|
||||||
self.logger.info("Note: conflicting default masters:\n\tUsing %s as default\n\tMutator found %s" % (flaggedDefaultCandidate.name, mutatorDefaultCandidate.name))
|
|
||||||
self.default = flaggedDefaultCandidate
|
|
||||||
self.defaultLoc = self.default.location
|
|
||||||
else:
|
|
||||||
# we have no flagged default candidate
|
|
||||||
# let's use the one from mutator
|
|
||||||
if flaggedDefaultCandidate is None and mutatorDefaultCandidate is not None:
|
|
||||||
# we didn't have a flag, use the one selected by mutator
|
|
||||||
self.default = mutatorDefaultCandidate
|
|
||||||
self.defaultLoc = self.default.location
|
|
||||||
self.default.copyInfo = True
|
|
||||||
# now that we have a default, let's check if the axes are ok
|
|
||||||
for axisObj in self.axes:
|
|
||||||
if axisObj.name not in self.default.location:
|
|
||||||
# extend the location of the neutral master with missing default value for this axis
|
|
||||||
self.default.location[axisObj.name] = axisObj.default
|
|
||||||
else:
|
|
||||||
if axisObj.default == self.default.location.get(axisObj.name):
|
|
||||||
continue
|
|
||||||
# proposed remedy: change default value in the axisdescriptor to the value of the neutral
|
|
||||||
neutralAxisValue = self.default.location.get(axisObj.name)
|
|
||||||
# make sure this value is between the min and max
|
|
||||||
if axisObj.minimum <= neutralAxisValue <= axisObj.maximum:
|
|
||||||
# yes we can fix this
|
|
||||||
axisObj.default = neutralAxisValue
|
|
||||||
self.logger.info("Note: updating the default value of axis %s to neutral master at %3.3f" % (axisObj.name, neutralAxisValue))
|
|
||||||
# always fit the axis dimensions to the location of the designated neutral
|
|
||||||
elif neutralAxisValue < axisObj.minimum:
|
|
||||||
axisObj.default = neutralAxisValue
|
|
||||||
axisObj.minimum = neutralAxisValue
|
|
||||||
elif neutralAxisValue > axisObj.maximum:
|
|
||||||
axisObj.maximum = neutralAxisValue
|
|
||||||
axisObj.default = neutralAxisValue
|
|
||||||
else:
|
|
||||||
# now we're in trouble, can't solve this, alert.
|
|
||||||
self.logger.info("Warning: mismatched default value for axis %s and neutral master. Master value outside of axis bounds" % (axisObj.name))
|
|
||||||
|
|
||||||
def getMutatorDefaultCandidate(self):
|
|
||||||
# FIXME: original implementation using MutatorMath
|
|
||||||
# masterLocations = [src.location for src in self.sources]
|
|
||||||
# mutatorBias = biasFromLocations(masterLocations, preferOrigin=False)
|
|
||||||
# for src in self.sources:
|
|
||||||
# if src.location == mutatorBias:
|
|
||||||
# return src
|
|
||||||
return None
|
return None
|
||||||
|
|
||||||
def _prepAxesForBender(self):
|
def _prepAxesForBender(self):
|
||||||
@ -1360,7 +1305,6 @@ class DesignSpaceDocument(object):
|
|||||||
a.tag, a.labelNames = tagForAxisName(a.name)
|
a.tag, a.labelNames = tagForAxisName(a.name)
|
||||||
self.logger.info("CheckAxes: added a missing axis %s, %3.3f %3.3f", a.name, a.minimum, a.maximum)
|
self.logger.info("CheckAxes: added a missing axis %s, %3.3f %3.3f", a.name, a.minimum, a.maximum)
|
||||||
|
|
||||||
|
|
||||||
def normalizeLocation(self, location):
|
def normalizeLocation(self, location):
|
||||||
# scale this location based on the axes
|
# scale this location based on the axes
|
||||||
# accept only values for the axes that we have definitions for
|
# accept only values for the axes that we have definitions for
|
||||||
@ -1439,20 +1383,3 @@ class DesignSpaceDocument(object):
|
|||||||
newConditionSets.append(newConditions)
|
newConditionSets.append(newConditions)
|
||||||
rule.conditionSets = newConditionSets
|
rule.conditionSets = newConditionSets
|
||||||
|
|
||||||
|
|
||||||
def rulesToFeature(doc, whiteSpace="\t", newLine="\n"):
|
|
||||||
""" Showing how rules could be expressed as FDK feature text.
|
|
||||||
Speculative. Experimental.
|
|
||||||
"""
|
|
||||||
axisNames = {axis.name: axis.tag for axis in doc.axes}
|
|
||||||
axisDims = {axis.tag: (axis.minimum, axis.maximum) for axis in doc.axes}
|
|
||||||
text = []
|
|
||||||
for rule in doc.rules:
|
|
||||||
text.append("rule %s{" % rule.name)
|
|
||||||
for cd in rule.conditions:
|
|
||||||
axisTag = axisNames.get(cd.get('name'), "****")
|
|
||||||
axisMinimum = cd.get('minimum', axisDims.get(axisTag, [0,0])[0])
|
|
||||||
axisMaximum = cd.get('maximum', axisDims.get(axisTag, [0,0])[1])
|
|
||||||
text.append("%s%s %f %f;" % (whiteSpace, axisTag, axisMinimum, axisMaximum))
|
|
||||||
text.append("} %s;" % rule.name)
|
|
||||||
return newLine.join(text)
|
|
||||||
|
@ -31,6 +31,29 @@ def test_fill_document(tmpdir):
|
|||||||
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
||||||
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
|
||||||
|
# write some axes
|
||||||
|
a1 = AxisDescriptor()
|
||||||
|
a1.minimum = 0
|
||||||
|
a1.maximum = 1000
|
||||||
|
a1.default = 0
|
||||||
|
a1.name = "weight"
|
||||||
|
a1.tag = "wght"
|
||||||
|
# note: just to test the element language, not an actual label name recommendations.
|
||||||
|
a1.labelNames[u'fa-IR'] = u"قطر"
|
||||||
|
a1.labelNames[u'en'] = u"Wéíght"
|
||||||
|
doc.addAxis(a1)
|
||||||
|
a2 = AxisDescriptor()
|
||||||
|
a2.minimum = 0
|
||||||
|
a2.maximum = 1000
|
||||||
|
a2.default = 20
|
||||||
|
a2.name = "width"
|
||||||
|
a2.tag = "wdth"
|
||||||
|
a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
||||||
|
a2.hidden = True
|
||||||
|
a2.labelNames[u'fr'] = u"Chasse"
|
||||||
|
doc.addAxis(a2)
|
||||||
|
|
||||||
# add master 1
|
# add master 1
|
||||||
s1 = SourceDescriptor()
|
s1 = SourceDescriptor()
|
||||||
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
||||||
@ -107,45 +130,6 @@ def test_fill_document(tmpdir):
|
|||||||
doc.filename = "suggestedFileName.designspace"
|
doc.filename = "suggestedFileName.designspace"
|
||||||
doc.lib['com.coolDesignspaceApp.previewSize'] = 30
|
doc.lib['com.coolDesignspaceApp.previewSize'] = 30
|
||||||
|
|
||||||
# now we have sources and instances, but no axes yet.
|
|
||||||
doc.check()
|
|
||||||
|
|
||||||
# Here, since the axes are not defined in the document, but instead are
|
|
||||||
# infered from the locations of the instances, we cannot guarantee the
|
|
||||||
# order in which they will be created by the `check()` method.
|
|
||||||
assert set(doc.getAxisOrder()) == set(['spooky', 'weight', 'width'])
|
|
||||||
doc.axes = [] # clear the axes
|
|
||||||
|
|
||||||
# write some axes
|
|
||||||
a1 = AxisDescriptor()
|
|
||||||
a1.minimum = 0
|
|
||||||
a1.maximum = 1000
|
|
||||||
a1.default = 0
|
|
||||||
a1.name = "weight"
|
|
||||||
a1.tag = "wght"
|
|
||||||
# note: just to test the element language, not an actual label name recommendations.
|
|
||||||
a1.labelNames[u'fa-IR'] = u"قطر"
|
|
||||||
a1.labelNames[u'en'] = u"Wéíght"
|
|
||||||
doc.addAxis(a1)
|
|
||||||
a2 = AxisDescriptor()
|
|
||||||
a2.minimum = 0
|
|
||||||
a2.maximum = 1000
|
|
||||||
a2.default = 20
|
|
||||||
a2.name = "width"
|
|
||||||
a2.tag = "wdth"
|
|
||||||
a2.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
||||||
a2.hidden = True
|
|
||||||
a2.labelNames[u'fr'] = u"Chasse"
|
|
||||||
doc.addAxis(a2)
|
|
||||||
# add an axis that is not part of any location to see if that works
|
|
||||||
a3 = AxisDescriptor()
|
|
||||||
a3.minimum = 333
|
|
||||||
a3.maximum = 666
|
|
||||||
a3.default = 444
|
|
||||||
a3.name = "spooky"
|
|
||||||
a3.tag = "SPOK"
|
|
||||||
a3.map = [(0.0, 10.0), (401.0, 66.0), (1000.0, 990.0)]
|
|
||||||
#doc.addAxis(a3) # uncomment this line to test the effects of default axes values
|
|
||||||
# write some rules
|
# write some rules
|
||||||
r1 = RuleDescriptor()
|
r1 = RuleDescriptor()
|
||||||
r1.name = "named.rule.1"
|
r1.name = "named.rule.1"
|
||||||
@ -163,23 +147,11 @@ def test_fill_document(tmpdir):
|
|||||||
new = DesignSpaceDocument()
|
new = DesignSpaceDocument()
|
||||||
new.read(testDocPath)
|
new.read(testDocPath)
|
||||||
|
|
||||||
new.check()
|
|
||||||
assert new.default.location == {'width': 20.0, 'weight': 0.0}
|
assert new.default.location == {'width': 20.0, 'weight': 0.0}
|
||||||
assert new.filename == 'test.designspace'
|
assert new.filename == 'test.designspace'
|
||||||
assert new.lib == doc.lib
|
assert new.lib == doc.lib
|
||||||
assert new.instances[0].lib == doc.instances[0].lib
|
assert new.instances[0].lib == doc.instances[0].lib
|
||||||
|
|
||||||
# >>> for a, b in zip(doc.instances, new.instances):
|
|
||||||
# ... a.compare(b)
|
|
||||||
# >>> for a, b in zip(doc.sources, new.sources):
|
|
||||||
# ... a.compare(b)
|
|
||||||
# >>> for a, b in zip(doc.axes, new.axes):
|
|
||||||
# ... a.compare(b)
|
|
||||||
# >>> [n.mutedGlyphNames for n in new.sources]
|
|
||||||
# [['A', 'Z'], []]
|
|
||||||
# >>> doc.getFonts()
|
|
||||||
# []
|
|
||||||
|
|
||||||
# test roundtrip for the axis attributes and data
|
# test roundtrip for the axis attributes and data
|
||||||
axes = {}
|
axes = {}
|
||||||
for axis in doc.axes:
|
for axis in doc.axes:
|
||||||
@ -197,50 +169,6 @@ def test_fill_document(tmpdir):
|
|||||||
assert a == b
|
assert a == b
|
||||||
|
|
||||||
|
|
||||||
def test_adjustAxisDefaultToNeutral(tmpdir):
|
|
||||||
tmpdir = str(tmpdir)
|
|
||||||
testDocPath = os.path.join(tmpdir, "testAdjustAxisDefaultToNeutral.designspace")
|
|
||||||
masterPath1 = os.path.join(tmpdir, "masters", "masterTest1.ufo")
|
|
||||||
masterPath2 = os.path.join(tmpdir, "masters", "masterTest2.ufo")
|
|
||||||
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
|
||||||
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
|
||||||
doc = DesignSpaceDocument()
|
|
||||||
# add master 1
|
|
||||||
s1 = SourceDescriptor()
|
|
||||||
s1.filename = os.path.relpath(masterPath1, os.path.dirname(testDocPath))
|
|
||||||
s1.name = "master.ufo1"
|
|
||||||
s1.copyInfo = True
|
|
||||||
s1.copyFeatures = True
|
|
||||||
s1.location = dict(weight=55, width=1000)
|
|
||||||
doc.addSource(s1)
|
|
||||||
# write some axes
|
|
||||||
a1 = AxisDescriptor()
|
|
||||||
a1.minimum = 0
|
|
||||||
a1.maximum = 1000
|
|
||||||
a1.default = 0 # the wrong value
|
|
||||||
a1.name = "weight"
|
|
||||||
a1.tag = "wght"
|
|
||||||
doc.addAxis(a1)
|
|
||||||
a2 = AxisDescriptor()
|
|
||||||
a2.minimum = -10
|
|
||||||
a2.maximum = 10
|
|
||||||
a2.default = 0 # the wrong value
|
|
||||||
a2.name = "width"
|
|
||||||
a2.tag = "wdth"
|
|
||||||
doc.addAxis(a2)
|
|
||||||
# write the document
|
|
||||||
doc.write(testDocPath)
|
|
||||||
assert os.path.exists(testDocPath)
|
|
||||||
# import it again
|
|
||||||
new = DesignSpaceDocument()
|
|
||||||
new.read(testDocPath)
|
|
||||||
new.check()
|
|
||||||
loc = new.default.location
|
|
||||||
for axisObj in new.axes:
|
|
||||||
n = axisObj.name
|
|
||||||
assert axisObj.default == loc.get(n)
|
|
||||||
|
|
||||||
|
|
||||||
def test_unicodes(tmpdir):
|
def test_unicodes(tmpdir):
|
||||||
tmpdir = str(tmpdir)
|
tmpdir = str(tmpdir)
|
||||||
testDocPath = os.path.join(tmpdir, "testUnicodes.designspace")
|
testDocPath = os.path.join(tmpdir, "testUnicodes.designspace")
|
||||||
@ -457,7 +385,7 @@ def test_handleNoAxes(tmpdir):
|
|||||||
doc.addInstance(i1)
|
doc.addInstance(i1)
|
||||||
|
|
||||||
doc.write(testDocPath)
|
doc.write(testDocPath)
|
||||||
__removeAxesFromDesignSpace(testDocPath)
|
#__removeAxesFromDesignSpace(testDocPath)
|
||||||
verify = DesignSpaceDocument()
|
verify = DesignSpaceDocument()
|
||||||
verify.read(testDocPath)
|
verify.read(testDocPath)
|
||||||
verify.write(testDocPath2)
|
verify.write(testDocPath2)
|
||||||
@ -476,8 +404,16 @@ def test_pathNameResolve(tmpdir):
|
|||||||
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
instancePath1 = os.path.join(tmpdir, "instances", "instanceTest1.ufo")
|
||||||
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
instancePath2 = os.path.join(tmpdir, "instances", "instanceTest2.ufo")
|
||||||
|
|
||||||
|
a1 = AxisDescriptor()
|
||||||
|
a1.tag = "TAGA"
|
||||||
|
a1.name = "axisName_a"
|
||||||
|
a1.minimum = 0
|
||||||
|
a1.maximum = 1000
|
||||||
|
a1.default = 0
|
||||||
|
|
||||||
# Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file.
|
# Case 1: filename and path are both empty. Nothing to calculate, nothing to put in the file.
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = None
|
s.filename = None
|
||||||
s.path = None
|
s.path = None
|
||||||
@ -494,6 +430,7 @@ def test_pathNameResolve(tmpdir):
|
|||||||
|
|
||||||
# Case 2: filename is empty, path points somewhere: calculate a new filename.
|
# Case 2: filename is empty, path points somewhere: calculate a new filename.
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = None
|
s.filename = None
|
||||||
s.path = masterPath1
|
s.path = masterPath1
|
||||||
@ -510,6 +447,7 @@ def test_pathNameResolve(tmpdir):
|
|||||||
|
|
||||||
# Case 3: the filename is set, the path is None.
|
# Case 3: the filename is set, the path is None.
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = "../somewhere/over/the/rainbow.ufo"
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
||||||
s.path = None
|
s.path = None
|
||||||
@ -528,6 +466,7 @@ def test_pathNameResolve(tmpdir):
|
|||||||
|
|
||||||
# Case 4: the filename points to one file, the path points to another. The path takes precedence.
|
# Case 4: the filename points to one file, the path points to another. The path takes precedence.
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = "../somewhere/over/the/rainbow.ufo"
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
||||||
s.path = masterPath1
|
s.path = masterPath1
|
||||||
@ -543,6 +482,7 @@ def test_pathNameResolve(tmpdir):
|
|||||||
|
|
||||||
# Case 5: the filename is None, path has a value, update the filename
|
# Case 5: the filename is None, path has a value, update the filename
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = None
|
s.filename = None
|
||||||
s.path = masterPath1
|
s.path = masterPath1
|
||||||
@ -557,6 +497,7 @@ def test_pathNameResolve(tmpdir):
|
|||||||
|
|
||||||
# Case 6: the filename has a value, path has a value, update the filenames with force
|
# Case 6: the filename has a value, path has a value, update the filenames with force
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
doc.addAxis(a1)
|
||||||
s = SourceDescriptor()
|
s = SourceDescriptor()
|
||||||
s.filename = "../somewhere/over/the/rainbow.ufo"
|
s.filename = "../somewhere/over/the/rainbow.ufo"
|
||||||
s.path = masterPath1
|
s.path = masterPath1
|
||||||
@ -802,6 +743,22 @@ def test_incompleteRule(tmpdir):
|
|||||||
tmpdir = str(tmpdir)
|
tmpdir = str(tmpdir)
|
||||||
testDocPath1 = os.path.join(tmpdir, "testIncompleteRule.designspace")
|
testDocPath1 = os.path.join(tmpdir, "testIncompleteRule.designspace")
|
||||||
doc = DesignSpaceDocument()
|
doc = DesignSpaceDocument()
|
||||||
|
# write some axes
|
||||||
|
a1 = AxisDescriptor()
|
||||||
|
a1.tag = "TAGA"
|
||||||
|
a1.name = "axisName_a"
|
||||||
|
a1.minimum = 0
|
||||||
|
a1.maximum = 1000
|
||||||
|
a1.default = 0
|
||||||
|
doc.addAxis(a1)
|
||||||
|
a2 = AxisDescriptor()
|
||||||
|
a2.tag = "TAGB"
|
||||||
|
a2.name = "axisName_b"
|
||||||
|
a2.minimum = 0
|
||||||
|
a2.maximum = 3000
|
||||||
|
a2.default = 0
|
||||||
|
doc.addAxis(a2)
|
||||||
|
|
||||||
r1 = RuleDescriptor()
|
r1 = RuleDescriptor()
|
||||||
r1.name = "incomplete.rule.1"
|
r1.name = "incomplete.rule.1"
|
||||||
r1.conditionSets.append([
|
r1.conditionSets.append([
|
||||||
|
Loading…
x
Reference in New Issue
Block a user