Check for descriptor types with hasattr() to allow custom classes that don't inherit the default descriptors
This commit is contained in:
parent
42e4d66184
commit
ec4bcf54c9
@ -8,7 +8,7 @@ import os
|
|||||||
import posixpath
|
import posixpath
|
||||||
from io import BytesIO, StringIO
|
from io import BytesIO, StringIO
|
||||||
from textwrap import indent
|
from textwrap import indent
|
||||||
from typing import Any, Dict, List, MutableMapping, Optional, Tuple, Union
|
from typing import Any, Dict, List, MutableMapping, Optional, Tuple, Union, cast
|
||||||
|
|
||||||
from fontTools.misc import etree as ET
|
from fontTools.misc import etree as ET
|
||||||
from fontTools.misc import plistlib
|
from fontTools.misc import plistlib
|
||||||
@ -1352,7 +1352,7 @@ class BaseDocWriter(object):
|
|||||||
minVersion = self.documentObject.formatTuple
|
minVersion = self.documentObject.formatTuple
|
||||||
if (
|
if (
|
||||||
any(
|
any(
|
||||||
isinstance(axis, DiscreteAxisDescriptor) or
|
hasattr(axis, 'values') or
|
||||||
axis.axisOrdering is not None or
|
axis.axisOrdering is not None or
|
||||||
axis.axisLabels
|
axis.axisLabels
|
||||||
for axis in self.documentObject.axes
|
for axis in self.documentObject.axes
|
||||||
@ -1445,10 +1445,10 @@ class BaseDocWriter(object):
|
|||||||
for label in axisObject.axisLabels:
|
for label in axisObject.axisLabels:
|
||||||
self._addAxisLabel(labelsElement, label)
|
self._addAxisLabel(labelsElement, label)
|
||||||
axisElement.append(labelsElement)
|
axisElement.append(labelsElement)
|
||||||
if isinstance(axisObject, AxisDescriptor):
|
if hasattr(axisObject, "minimum"):
|
||||||
axisElement.attrib['minimum'] = self.intOrFloat(axisObject.minimum)
|
axisElement.attrib['minimum'] = self.intOrFloat(axisObject.minimum)
|
||||||
axisElement.attrib['maximum'] = self.intOrFloat(axisObject.maximum)
|
axisElement.attrib['maximum'] = self.intOrFloat(axisObject.maximum)
|
||||||
elif isinstance(axisObject, DiscreteAxisDescriptor):
|
elif hasattr(axisObject, "values"):
|
||||||
axisElement.attrib['values'] = " ".join(self.intOrFloat(v) for v in axisObject.values)
|
axisElement.attrib['values'] = " ".join(self.intOrFloat(v) for v in axisObject.values)
|
||||||
axisElement.attrib['default'] = self.intOrFloat(axisObject.default)
|
axisElement.attrib['default'] = self.intOrFloat(axisObject.default)
|
||||||
if axisObject.hidden:
|
if axisObject.hidden:
|
||||||
@ -1682,14 +1682,19 @@ class BaseDocWriter(object):
|
|||||||
for subset in vf.axisSubsets:
|
for subset in vf.axisSubsets:
|
||||||
subsetElement = ET.Element('axis-subset')
|
subsetElement = ET.Element('axis-subset')
|
||||||
subsetElement.attrib['name'] = subset.name
|
subsetElement.attrib['name'] = subset.name
|
||||||
if isinstance(subset, RangeAxisSubsetDescriptor):
|
# Mypy doesn't support narrowing union types via hasattr()
|
||||||
|
# https://mypy.readthedocs.io/en/stable/type_narrowing.html
|
||||||
|
# TODO(Python 3.10): use TypeGuard
|
||||||
|
if hasattr(subset, "userMinimum"):
|
||||||
|
subset = cast(RangeAxisSubsetDescriptor, subset)
|
||||||
if subset.userMinimum != -math.inf:
|
if subset.userMinimum != -math.inf:
|
||||||
subsetElement.attrib['userminimum'] = self.intOrFloat(subset.userMinimum)
|
subsetElement.attrib['userminimum'] = self.intOrFloat(subset.userMinimum)
|
||||||
if subset.userMaximum != math.inf:
|
if subset.userMaximum != math.inf:
|
||||||
subsetElement.attrib['usermaximum'] = self.intOrFloat(subset.userMaximum)
|
subsetElement.attrib['usermaximum'] = self.intOrFloat(subset.userMaximum)
|
||||||
if subset.userDefault is not None:
|
if subset.userDefault is not None:
|
||||||
subsetElement.attrib['userdefault'] = self.intOrFloat(subset.userDefault)
|
subsetElement.attrib['userdefault'] = self.intOrFloat(subset.userDefault)
|
||||||
elif isinstance(subset, ValueAxisSubsetDescriptor):
|
elif hasattr(subset, "userValue"):
|
||||||
|
subset = cast(ValueAxisSubsetDescriptor, subset)
|
||||||
subsetElement.attrib['uservalue'] = self.intOrFloat(subset.userValue)
|
subsetElement.attrib['uservalue'] = self.intOrFloat(subset.userValue)
|
||||||
subsetsElement.append(subsetElement)
|
subsetsElement.append(subsetElement)
|
||||||
vfElement.append(subsetsElement)
|
vfElement.append(subsetsElement)
|
||||||
@ -2904,8 +2909,12 @@ class DesignSpaceDocument(LogMixin, AsDictMixin):
|
|||||||
discreteAxes = []
|
discreteAxes = []
|
||||||
rangeAxisSubsets: List[Union[RangeAxisSubsetDescriptor, ValueAxisSubsetDescriptor]] = []
|
rangeAxisSubsets: List[Union[RangeAxisSubsetDescriptor, ValueAxisSubsetDescriptor]] = []
|
||||||
for axis in self.axes:
|
for axis in self.axes:
|
||||||
if isinstance(axis, DiscreteAxisDescriptor):
|
if hasattr(axis, "values"):
|
||||||
discreteAxes.append(axis)
|
# Mypy doesn't support narrowing union types via hasattr()
|
||||||
|
# TODO(Python 3.10): use TypeGuard
|
||||||
|
# https://mypy.readthedocs.io/en/stable/type_narrowing.html
|
||||||
|
axis = cast(DiscreteAxisDescriptor, axis)
|
||||||
|
discreteAxes.append(axis) # type: ignore
|
||||||
else:
|
else:
|
||||||
rangeAxisSubsets.append(RangeAxisSubsetDescriptor(name=axis.name))
|
rangeAxisSubsets.append(RangeAxisSubsetDescriptor(name=axis.name))
|
||||||
valueCombinations = itertools.product(*[axis.values for axis in discreteAxes])
|
valueCombinations = itertools.product(*[axis.values for axis in discreteAxes])
|
||||||
|
@ -7,7 +7,7 @@ from __future__ import annotations
|
|||||||
import itertools
|
import itertools
|
||||||
import logging
|
import logging
|
||||||
import math
|
import math
|
||||||
from typing import Any, Callable, Dict, Iterator, List, Tuple
|
from typing import Any, Callable, Dict, Iterator, List, Tuple, cast
|
||||||
|
|
||||||
from fontTools.designspaceLib import (
|
from fontTools.designspaceLib import (
|
||||||
AxisDescriptor,
|
AxisDescriptor,
|
||||||
@ -21,9 +21,9 @@ from fontTools.designspaceLib import (
|
|||||||
)
|
)
|
||||||
from fontTools.designspaceLib.statNames import StatNames, getStatNames
|
from fontTools.designspaceLib.statNames import StatNames, getStatNames
|
||||||
from fontTools.designspaceLib.types import (
|
from fontTools.designspaceLib.types import (
|
||||||
|
ConditionSet,
|
||||||
Range,
|
Range,
|
||||||
Region,
|
Region,
|
||||||
ConditionSet,
|
|
||||||
getVFUserRegion,
|
getVFUserRegion,
|
||||||
locationInRegion,
|
locationInRegion,
|
||||||
regionInRegion,
|
regionInRegion,
|
||||||
@ -87,11 +87,18 @@ def splitInterpolable(
|
|||||||
discreteAxes = []
|
discreteAxes = []
|
||||||
interpolableUserRegion: Region = {}
|
interpolableUserRegion: Region = {}
|
||||||
for axis in doc.axes:
|
for axis in doc.axes:
|
||||||
if isinstance(axis, DiscreteAxisDescriptor):
|
if hasattr(axis, "values"):
|
||||||
|
# Mypy doesn't support narrowing union types via hasattr()
|
||||||
|
# TODO(Python 3.10): use TypeGuard
|
||||||
|
# https://mypy.readthedocs.io/en/stable/type_narrowing.html
|
||||||
|
axis = cast(DiscreteAxisDescriptor, axis)
|
||||||
discreteAxes.append(axis)
|
discreteAxes.append(axis)
|
||||||
else:
|
else:
|
||||||
|
axis = cast(AxisDescriptor, axis)
|
||||||
interpolableUserRegion[axis.name] = Range(
|
interpolableUserRegion[axis.name] = Range(
|
||||||
axis.minimum, axis.maximum, axis.default
|
axis.minimum,
|
||||||
|
axis.maximum,
|
||||||
|
axis.default,
|
||||||
)
|
)
|
||||||
valueCombinations = itertools.product(*[axis.values for axis in discreteAxes])
|
valueCombinations = itertools.product(*[axis.values for axis in discreteAxes])
|
||||||
for values in valueCombinations:
|
for values in valueCombinations:
|
||||||
@ -191,7 +198,11 @@ def _extractSubSpace(
|
|||||||
|
|
||||||
for axis in doc.axes:
|
for axis in doc.axes:
|
||||||
range = userRegion[axis.name]
|
range = userRegion[axis.name]
|
||||||
if isinstance(range, Range) and isinstance(axis, AxisDescriptor):
|
if isinstance(range, Range) and hasattr(axis, "minimum"):
|
||||||
|
# Mypy doesn't support narrowing union types via hasattr()
|
||||||
|
# TODO(Python 3.10): use TypeGuard
|
||||||
|
# https://mypy.readthedocs.io/en/stable/type_narrowing.html
|
||||||
|
axis = cast(AxisDescriptor, axis)
|
||||||
subDoc.addAxis(
|
subDoc.addAxis(
|
||||||
AxisDescriptor(
|
AxisDescriptor(
|
||||||
# Same info
|
# Same info
|
||||||
|
@ -1,14 +1,15 @@
|
|||||||
from __future__ import annotations
|
from __future__ import annotations
|
||||||
|
|
||||||
from dataclasses import dataclass
|
from dataclasses import dataclass
|
||||||
from typing import Dict, List, Optional, Union
|
from typing import Dict, List, Optional, Union, cast
|
||||||
|
|
||||||
from fontTools.designspaceLib import (
|
from fontTools.designspaceLib import (
|
||||||
|
AxisDescriptor,
|
||||||
DesignSpaceDocument,
|
DesignSpaceDocument,
|
||||||
DesignSpaceDocumentError,
|
DesignSpaceDocumentError,
|
||||||
DiscreteAxisDescriptor,
|
|
||||||
RangeAxisSubsetDescriptor,
|
RangeAxisSubsetDescriptor,
|
||||||
SimpleLocationDict,
|
SimpleLocationDict,
|
||||||
|
ValueAxisSubsetDescriptor,
|
||||||
VariableFontDescriptor,
|
VariableFontDescriptor,
|
||||||
)
|
)
|
||||||
|
|
||||||
@ -117,18 +118,24 @@ def getVFUserRegion(doc: DesignSpaceDocument, vf: VariableFontDescriptor) -> Reg
|
|||||||
raise DesignSpaceDocumentError(
|
raise DesignSpaceDocumentError(
|
||||||
f"Cannot find axis named '{axisSubset.name}' for variable font '{vf.name}'."
|
f"Cannot find axis named '{axisSubset.name}' for variable font '{vf.name}'."
|
||||||
)
|
)
|
||||||
if isinstance(axisSubset, RangeAxisSubsetDescriptor):
|
if hasattr(axisSubset, "userMinimum"):
|
||||||
if isinstance(axis, DiscreteAxisDescriptor):
|
# Mypy doesn't support narrowing union types via hasattr()
|
||||||
|
# TODO(Python 3.10): use TypeGuard
|
||||||
|
# https://mypy.readthedocs.io/en/stable/type_narrowing.html
|
||||||
|
axisSubset = cast(RangeAxisSubsetDescriptor, axisSubset)
|
||||||
|
if not hasattr(axis, "minimum"):
|
||||||
raise DesignSpaceDocumentError(
|
raise DesignSpaceDocumentError(
|
||||||
f"Cannot select a range over '{axis.name}' for variable font '{vf.name}' "
|
f"Cannot select a range over '{axis.name}' for variable font '{vf.name}' "
|
||||||
"because it's a discrete axis, use only 'userValue' instead."
|
"because it's a discrete axis, use only 'userValue' instead."
|
||||||
)
|
)
|
||||||
|
axis = cast(AxisDescriptor, axis)
|
||||||
vfUserRegion[axis.name] = Range(
|
vfUserRegion[axis.name] = Range(
|
||||||
max(axisSubset.userMinimum, axis.minimum),
|
max(axisSubset.userMinimum, axis.minimum),
|
||||||
min(axisSubset.userMaximum, axis.maximum),
|
min(axisSubset.userMaximum, axis.maximum),
|
||||||
axisSubset.userDefault or axis.default,
|
axisSubset.userDefault or axis.default,
|
||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
|
axisSubset = cast(ValueAxisSubsetDescriptor, axisSubset)
|
||||||
vfUserRegion[axis.name] = axisSubset.userValue
|
vfUserRegion[axis.name] = axisSubset.userValue
|
||||||
# Any axis not mentioned explicitly has a single location = default value
|
# Any axis not mentioned explicitly has a single location = default value
|
||||||
for axis in doc.axes:
|
for axis in doc.axes:
|
||||||
|
Loading…
x
Reference in New Issue
Block a user