Merge pull request #1860 from anthrotype/dslib-constructors
designspaceLib: allow to construct descriptors from keyword args
This commit is contained in:
commit
c43c6b2d99
@ -100,14 +100,32 @@ class SourceDescriptor(SimpleDescriptor):
|
|||||||
'mutedGlyphNames',
|
'mutedGlyphNames',
|
||||||
'familyName', 'styleName']
|
'familyName', 'styleName']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(
|
||||||
self.filename = None
|
self,
|
||||||
|
*,
|
||||||
|
filename=None,
|
||||||
|
path=None,
|
||||||
|
font=None,
|
||||||
|
name=None,
|
||||||
|
location=None,
|
||||||
|
layerName=None,
|
||||||
|
familyName=None,
|
||||||
|
styleName=None,
|
||||||
|
copyLib=False,
|
||||||
|
copyInfo=False,
|
||||||
|
copyGroups=False,
|
||||||
|
copyFeatures=False,
|
||||||
|
muteKerning=False,
|
||||||
|
muteInfo=False,
|
||||||
|
mutedGlyphNames=None,
|
||||||
|
):
|
||||||
|
self.filename = filename
|
||||||
"""The original path as found in the document."""
|
"""The original path as found in the document."""
|
||||||
|
|
||||||
self.path = None
|
self.path = path
|
||||||
"""The absolute path, calculated from filename."""
|
"""The absolute path, calculated from filename."""
|
||||||
|
|
||||||
self.font = None
|
self.font = font
|
||||||
"""Any Python object. Optional. Points to a representation of this
|
"""Any Python object. Optional. Points to a representation of this
|
||||||
source font that is loaded in memory, as a Python object (e.g. a
|
source font that is loaded in memory, as a Python object (e.g. a
|
||||||
``defcon.Font`` or a ``fontTools.ttFont.TTFont``).
|
``defcon.Font`` or a ``fontTools.ttFont.TTFont``).
|
||||||
@ -119,18 +137,19 @@ class SourceDescriptor(SimpleDescriptor):
|
|||||||
this field to the disk and make ```filename`` point to that.
|
this field to the disk and make ```filename`` point to that.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
self.name = None
|
self.name = name
|
||||||
self.location = None
|
self.location = location
|
||||||
self.layerName = None
|
self.layerName = layerName
|
||||||
self.copyLib = False
|
self.familyName = familyName
|
||||||
self.copyInfo = False
|
self.styleName = styleName
|
||||||
self.copyGroups = False
|
|
||||||
self.copyFeatures = False
|
self.copyLib = copyLib
|
||||||
self.muteKerning = False
|
self.copyInfo = copyInfo
|
||||||
self.muteInfo = False
|
self.copyGroups = copyGroups
|
||||||
self.mutedGlyphNames = []
|
self.copyFeatures = copyFeatures
|
||||||
self.familyName = None
|
self.muteKerning = muteKerning
|
||||||
self.styleName = None
|
self.muteInfo = muteInfo
|
||||||
|
self.mutedGlyphNames = mutedGlyphNames or []
|
||||||
|
|
||||||
path = posixpath_property("_path")
|
path = posixpath_property("_path")
|
||||||
filename = posixpath_property("_filename")
|
filename = posixpath_property("_filename")
|
||||||
@ -152,10 +171,12 @@ class RuleDescriptor(SimpleDescriptor):
|
|||||||
"""
|
"""
|
||||||
_attrs = ['name', 'conditionSets', 'subs'] # what do we need here
|
_attrs = ['name', 'conditionSets', 'subs'] # what do we need here
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(self, *, name=None, conditionSets=None, subs=None):
|
||||||
self.name = None
|
self.name = name
|
||||||
self.conditionSets = [] # list of list of dict(name='aaaa', minimum=0, maximum=1000)
|
# list of lists of dict(name='aaaa', minimum=0, maximum=1000)
|
||||||
self.subs = [] # list of substitutions stored as tuples of glyphnames ("a", "a.alt")
|
self.conditionSets = conditionSets or []
|
||||||
|
# list of substitutions stored as tuples of glyphnames ("a", "a.alt")
|
||||||
|
self.subs = subs or []
|
||||||
|
|
||||||
|
|
||||||
def evaluateRule(rule, location):
|
def evaluateRule(rule, location):
|
||||||
@ -219,26 +240,50 @@ class InstanceDescriptor(SimpleDescriptor):
|
|||||||
'info',
|
'info',
|
||||||
'lib']
|
'lib']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(
|
||||||
self.filename = None # the original path as found in the document
|
self,
|
||||||
self.path = None # the absolute path, calculated from filename
|
*,
|
||||||
self.font = None # Same as in SourceDescriptor.
|
filename=None,
|
||||||
self.name = None
|
path=None,
|
||||||
self.location = None
|
font=None,
|
||||||
self.familyName = None
|
name=None,
|
||||||
self.styleName = None
|
location=None,
|
||||||
self.postScriptFontName = None
|
familyName=None,
|
||||||
self.styleMapFamilyName = None
|
styleName=None,
|
||||||
self.styleMapStyleName = None
|
postScriptFontName=None,
|
||||||
self.localisedStyleName = {}
|
styleMapFamilyName=None,
|
||||||
self.localisedFamilyName = {}
|
styleMapStyleName=None,
|
||||||
self.localisedStyleMapStyleName = {}
|
localisedFamilyName=None,
|
||||||
self.localisedStyleMapFamilyName = {}
|
localisedStyleName=None,
|
||||||
self.glyphs = {}
|
localisedStyleMapFamilyName=None,
|
||||||
self.kerning = True
|
localisedStyleMapStyleName=None,
|
||||||
self.info = True
|
glyphs=None,
|
||||||
|
kerning=True,
|
||||||
|
info=True,
|
||||||
|
lib=None,
|
||||||
|
):
|
||||||
|
# the original path as found in the document
|
||||||
|
self.filename = filename
|
||||||
|
# the absolute path, calculated from filename
|
||||||
|
self.path = path
|
||||||
|
# Same as in SourceDescriptor.
|
||||||
|
self.font = font
|
||||||
|
self.name = name
|
||||||
|
self.location = location
|
||||||
|
self.familyName = familyName
|
||||||
|
self.styleName = styleName
|
||||||
|
self.postScriptFontName = postScriptFontName
|
||||||
|
self.styleMapFamilyName = styleMapFamilyName
|
||||||
|
self.styleMapStyleName = styleMapStyleName
|
||||||
|
self.localisedFamilyName = localisedFamilyName or {}
|
||||||
|
self.localisedStyleName = localisedStyleName or {}
|
||||||
|
self.localisedStyleMapFamilyName = localisedStyleMapFamilyName or {}
|
||||||
|
self.localisedStyleMapStyleName = localisedStyleMapStyleName or {}
|
||||||
|
self.glyphs = glyphs or {}
|
||||||
|
self.kerning = kerning
|
||||||
|
self.info = info
|
||||||
|
|
||||||
self.lib = {}
|
self.lib = lib or {}
|
||||||
"""Custom data associated with this instance."""
|
"""Custom data associated with this instance."""
|
||||||
|
|
||||||
path = posixpath_property("_path")
|
path = posixpath_property("_path")
|
||||||
@ -294,15 +339,29 @@ class AxisDescriptor(SimpleDescriptor):
|
|||||||
flavor = "axis"
|
flavor = "axis"
|
||||||
_attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map']
|
_attrs = ['tag', 'name', 'maximum', 'minimum', 'default', 'map']
|
||||||
|
|
||||||
def __init__(self):
|
def __init__(
|
||||||
self.tag = None # opentype tag for this axis
|
self,
|
||||||
self.name = None # name of the axis used in locations
|
*,
|
||||||
self.labelNames = {} # names for UI purposes, if this is not a standard axis,
|
tag=None,
|
||||||
self.minimum = None
|
name=None,
|
||||||
self.maximum = None
|
labelNames=None,
|
||||||
self.default = None
|
minimum=None,
|
||||||
self.hidden = False
|
default=None,
|
||||||
self.map = []
|
maximum=None,
|
||||||
|
hidden=False,
|
||||||
|
map=None,
|
||||||
|
):
|
||||||
|
# opentype tag for this axis
|
||||||
|
self.tag = tag
|
||||||
|
# name of the axis used in locations
|
||||||
|
self.name = name
|
||||||
|
# names for UI purposes, if this is not a standard axis,
|
||||||
|
self.labelNames = labelNames or {}
|
||||||
|
self.minimum = minimum
|
||||||
|
self.maximum = maximum
|
||||||
|
self.default = default
|
||||||
|
self.hidden = hidden
|
||||||
|
self.map = map or []
|
||||||
|
|
||||||
def serialize(self):
|
def serialize(self):
|
||||||
# output to a dict, used in testing
|
# output to a dict, used in testing
|
||||||
@ -1129,15 +1188,35 @@ class DesignSpaceDocument(LogMixin, AsDictMixin):
|
|||||||
def addSource(self, sourceDescriptor):
|
def addSource(self, sourceDescriptor):
|
||||||
self.sources.append(sourceDescriptor)
|
self.sources.append(sourceDescriptor)
|
||||||
|
|
||||||
|
def addSourceDescriptor(self, **kwargs):
|
||||||
|
source = self.writerClass.sourceDescriptorClass(**kwargs)
|
||||||
|
self.addSource(source)
|
||||||
|
return source
|
||||||
|
|
||||||
def addInstance(self, instanceDescriptor):
|
def addInstance(self, instanceDescriptor):
|
||||||
self.instances.append(instanceDescriptor)
|
self.instances.append(instanceDescriptor)
|
||||||
|
|
||||||
|
def addInstanceDescriptor(self, **kwargs):
|
||||||
|
instance = self.writerClass.instanceDescriptorClass(**kwargs)
|
||||||
|
self.addInstance(instance)
|
||||||
|
return instance
|
||||||
|
|
||||||
def addAxis(self, axisDescriptor):
|
def addAxis(self, axisDescriptor):
|
||||||
self.axes.append(axisDescriptor)
|
self.axes.append(axisDescriptor)
|
||||||
|
|
||||||
|
def addAxisDescriptor(self, **kwargs):
|
||||||
|
axis = self.writerClass.axisDescriptorClass(**kwargs)
|
||||||
|
self.addAxis(axis)
|
||||||
|
return axis
|
||||||
|
|
||||||
def addRule(self, ruleDescriptor):
|
def addRule(self, ruleDescriptor):
|
||||||
self.rules.append(ruleDescriptor)
|
self.rules.append(ruleDescriptor)
|
||||||
|
|
||||||
|
def addRuleDescriptor(self, **kwargs):
|
||||||
|
rule = self.writerClass.ruleDescriptorClass(**kwargs)
|
||||||
|
self.addRule(rule)
|
||||||
|
return rule
|
||||||
|
|
||||||
def newDefaultLocation(self):
|
def newDefaultLocation(self):
|
||||||
"""Return default location in design space."""
|
"""Return default location in design space."""
|
||||||
# Without OrderedDict, output XML would be non-deterministic.
|
# Without OrderedDict, output XML would be non-deterministic.
|
||||||
|
@ -949,3 +949,70 @@ def test_loadSourceFonts_no_required_path():
|
|||||||
|
|
||||||
with pytest.raises(DesignSpaceDocumentError, match="no 'path' attribute"):
|
with pytest.raises(DesignSpaceDocumentError, match="no 'path' attribute"):
|
||||||
designspace.loadSourceFonts(lambda p: p)
|
designspace.loadSourceFonts(lambda p: p)
|
||||||
|
|
||||||
|
|
||||||
|
def test_addAxisDescriptor():
|
||||||
|
ds = DesignSpaceDocument()
|
||||||
|
|
||||||
|
axis = ds.addAxisDescriptor(
|
||||||
|
name="Weight", tag="wght", minimum=100, default=400, maximum=900
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ds.axes[0] is axis
|
||||||
|
assert isinstance(axis, AxisDescriptor)
|
||||||
|
assert axis.name == "Weight"
|
||||||
|
assert axis.tag == "wght"
|
||||||
|
assert axis.minimum == 100
|
||||||
|
assert axis.default == 400
|
||||||
|
assert axis.maximum == 900
|
||||||
|
|
||||||
|
|
||||||
|
def test_addSourceDescriptor():
|
||||||
|
ds = DesignSpaceDocument()
|
||||||
|
|
||||||
|
source = ds.addSourceDescriptor(name="TestSource", location={"Weight": 400})
|
||||||
|
|
||||||
|
assert ds.sources[0] is source
|
||||||
|
assert isinstance(source, SourceDescriptor)
|
||||||
|
assert source.name == "TestSource"
|
||||||
|
assert source.location == {"Weight": 400}
|
||||||
|
|
||||||
|
|
||||||
|
def test_addInstanceDescriptor():
|
||||||
|
ds = DesignSpaceDocument()
|
||||||
|
|
||||||
|
instance = ds.addInstanceDescriptor(
|
||||||
|
name="TestInstance",
|
||||||
|
location={"Weight": 400},
|
||||||
|
styleName="Regular",
|
||||||
|
styleMapStyleName="regular",
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ds.instances[0] is instance
|
||||||
|
assert isinstance(instance, InstanceDescriptor)
|
||||||
|
assert instance.name == "TestInstance"
|
||||||
|
assert instance.location == {"Weight": 400}
|
||||||
|
assert instance.styleName == "Regular"
|
||||||
|
assert instance.styleMapStyleName == "regular"
|
||||||
|
|
||||||
|
|
||||||
|
def test_addRuleDescriptor():
|
||||||
|
ds = DesignSpaceDocument()
|
||||||
|
|
||||||
|
rule = ds.addRuleDescriptor(
|
||||||
|
name="TestRule",
|
||||||
|
conditionSets=[
|
||||||
|
dict(name='Weight', minimum=100, maximum=200),
|
||||||
|
dict(name='Weight', minimum=700, maximum=900),
|
||||||
|
],
|
||||||
|
subs=[("a", "a.alt")],
|
||||||
|
)
|
||||||
|
|
||||||
|
assert ds.rules[0] is rule
|
||||||
|
assert isinstance(rule, RuleDescriptor)
|
||||||
|
assert rule.name == "TestRule"
|
||||||
|
assert rule.conditionSets == [
|
||||||
|
dict(name='Weight', minimum=100, maximum=200),
|
||||||
|
dict(name='Weight', minimum=700, maximum=900),
|
||||||
|
]
|
||||||
|
assert rule.subs == [("a", "a.alt")]
|
||||||
|
Loading…
x
Reference in New Issue
Block a user