Created
May 18, 2018 10:31
-
-
Save madig/5df1e759f9108cc9cd729a4b6c3767ff to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
--- c:\\...\\development\\glyphslib\\Lib\\glyphsLib\\classes.py (original) | |
+++ c:\\...\\development\\glyphslib\\Lib\\glyphsLib\\classes.py (refactored) | |
@@ -33,6 +33,36 @@ | |
from collections import OrderedDict | |
from fontTools.misc.py23 import unicode, basestring, UnicodeIO, unichr, open | |
from glyphsLib.affine import Affine | |
+from glyphsLib.classes import GSLayer | |
+from typing import List | |
+from glyphsLib.classes import GSPath | |
+from typing import Optional | |
+from glyphsLib.classes import GSNode | |
+from _sre import SRE_Match | |
+from glyphsLib.classes import GSBackgroundLayer | |
+from typing import Union | |
+from glyphsLib.classes import segment | |
+from glyphsLib.types import Rect | |
+from glyphsLib.types import Point | |
+from typing import Tuple | |
+from glyphsLib.classes import GSGlyph | |
+from typing import Any | |
+from typing import Dict | |
+from mypy_extensions import NoReturn | |
+from glyphsLib.types import UnicodesList | |
+from glyphsLib.classes import GSFeature | |
+from glyphsLib.classes import GSInstance | |
+from typing import Callable | |
+from typing import Iterator | |
+from glyphsLib.classes import GSCustomParameter | |
+from glyphsLib.classes import GSFontMaster | |
+from glyphsLib.classes import GSClass | |
+from glyphsLib.classes import LayersIterator | |
+from glyphsLib.classes import GSAnchor | |
+from glyphsLib.classes import LayerAnchorsProxy | |
+from glyphsLib.classes import GSComponent | |
+from glyphsLib.classes import GSAlignmentZone | |
+from pathlib import WindowsPath | |
logger = logging.getLogger(__name__) | |
@@ -188,6 +218,7 @@ | |
def parse_hint_target(line=None): | |
+ # type: (Optional[str]) -> Optional[Point] | |
if line is None: | |
return None | |
if line[0] == "{": | |
@@ -197,10 +228,12 @@ | |
def isString(string): | |
+ # type: (str) -> bool | |
return isinstance(string, (str, unicode)) | |
def transformStructToScaleAndRotation(transform): | |
+ # type: (Union[List[float], List[int]]) -> Tuple[float, float, float] | |
Det = transform[0] * transform[3] - transform[1] * transform[2] | |
_sX = math.sqrt(math.pow(transform[0], 2) + math.pow(transform[1], 2)) | |
_sY = math.sqrt(math.pow(transform[2], 2) + math.pow(transform[3], 2)) | |
@@ -255,6 +288,7 @@ | |
_wrapperKeysTranslate = {} | |
def __init__(self): | |
+ # type: () -> None | |
for key in self._classesForName.keys(): | |
if not hasattr(self, key): | |
klass = self._classesForName[key] | |
@@ -270,12 +304,14 @@ | |
setattr(self, key, value) | |
def __repr__(self): | |
+ # type: () -> str | |
content = "" | |
if hasattr(self, "_dict"): | |
content = str(self._dict) | |
return "<%s %s>" % (self.__class__.__name__, content) | |
def classForName(self, name): | |
+ # type: (str) -> Union[Callable, None, type] | |
return self._classesForName.get(name, str) | |
def default_attr_value(self, attr_name): | |
@@ -292,6 +328,7 @@ | |
# Users of the library should only rely on the object-oriented API that is | |
# documented at https://docu.glyphsapp.com/ | |
def __setitem__(self, key, value): | |
+ # type: (str, Any) -> None | |
if isinstance(value, bytes) and key in self._classesForName: | |
new_type = self._classesForName[key] | |
if new_type is unicode: | |
@@ -305,6 +342,7 @@ | |
setattr(self, key, value) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
getKey = self._wrapperKeysTranslate.get(key, key) | |
value = getattr(self, getKey) | |
klass = self._classesForName[key] | |
@@ -323,9 +361,11 @@ | |
class Proxy(object): | |
def __init__(self, owner): | |
+ # type: (Any) -> None | |
self._owner = owner | |
def __repr__(self): | |
+ # type: () -> str | |
"""Return list-lookalike of representation string of objects""" | |
strings = [] | |
for currItem in self: | |
@@ -333,12 +373,14 @@ | |
return "(%s)" % (', '.join(strings)) | |
def __len__(self): | |
+ # type: () -> int | |
values = self.values() | |
if values is not None: | |
return len(values) | |
return 0 | |
def pop(self, i): | |
+ # type: (int) -> GSNode | |
if type(i) == int: | |
node = self[i] | |
del self[i] | |
@@ -347,12 +389,14 @@ | |
raise(KeyError) | |
def __iter__(self): | |
+ # type: () -> Iterator[Any] | |
values = self.values() | |
if values is not None: | |
for element in values: | |
yield element | |
def index(self, value): | |
+ # type: (GSNode) -> int | |
return self.values().index(value) | |
def __copy__(self): | |
@@ -362,6 +406,7 @@ | |
return [x.copy() for x in self.values()] | |
def setter(self, values): | |
+ # type: (List[GSCustomParameter]) -> None | |
method = self.setterMethod() | |
if type(values) == list: | |
method(values) | |
@@ -377,6 +422,7 @@ | |
class LayersIterator: | |
def __init__(self, owner): | |
+ # type: (GSGlyph) -> None | |
self.curInd = 0 | |
self._owner = owner | |
self._orderedLayers = None | |
@@ -388,6 +434,7 @@ | |
return self.__next__() | |
def __next__(self): | |
+ # type: () -> GSLayer | |
if self._owner.parent: | |
if self.curInd >= len(self._owner.layers): | |
raise StopIteration | |
@@ -401,6 +448,7 @@ | |
@property | |
def orderedLayers(self): | |
+ # type: () -> List[GSLayer] | |
if not self._orderedLayers: | |
glyphLayerIds = [ | |
l.associatedMasterId | |
@@ -432,6 +480,7 @@ | |
... | |
""" | |
def __getitem__(self, Key): | |
+ # type: (Union[int, str]) -> GSFontMaster | |
if type(Key) == slice: | |
return self.values().__getitem__(Key) | |
if type(Key) is int: | |
@@ -462,6 +511,7 @@ | |
raise(KeyError) | |
def __delitem__(self, Key): | |
+ # type: (int) -> Optional[Any] | |
if type(Key) is int: | |
if Key < 0: | |
Key = self.__len__() + Key | |
@@ -471,9 +521,11 @@ | |
return self.remove(OldFontMaster) | |
def values(self): | |
+ # type: () -> List[GSFontMaster] | |
return self._owner._masters | |
def append(self, FontMaster): | |
+ # type: (GSFontMaster) -> None | |
FontMaster.font = self._owner | |
if not FontMaster.id: | |
FontMaster.id = str(uuid.uuid4()).upper() | |
@@ -487,6 +539,7 @@ | |
glyph.layers.append(newLayer) | |
def remove(self, FontMaster): | |
+ # type: (GSFontMaster) -> None | |
# First remove all layers in all glyphs that reference this master | |
for glyph in self._owner.glyphs: | |
@@ -497,14 +550,17 @@ | |
self._owner._masters.remove(FontMaster) | |
def insert(self, Index, FontMaster): | |
+ # type: (int, GSFontMaster) -> None | |
FontMaster.font = self._owner | |
self._owner._masters.insert(Index, FontMaster) | |
def extend(self, FontMasters): | |
+ # type: (List[GSFontMaster]) -> None | |
for FontMaster in FontMasters: | |
self.append(FontMaster) | |
def setter(self, values): | |
+ # type: (List[GSFontMaster]) -> None | |
if isinstance(values, Proxy): | |
values = list(values) | |
self._owner._masters = values | |
@@ -521,6 +577,7 @@ | |
... | |
""" | |
def __getitem__(self, key): | |
+ # type: (Union[int, str]) -> Optional[GSGlyph] | |
if type(key) == slice: | |
return self.values().__getitem__(key) | |
@@ -547,11 +604,13 @@ | |
raise KeyError # TODO: add other access methods | |
def __contains__(self, item): | |
+ # type: (str) -> bool | |
if isString(item): | |
return self._get_glyph_by_string(item) is not None | |
return item in self._owner._glyphs | |
def _get_glyph_by_string(self, key): | |
+ # type: (str) -> Optional[GSGlyph] | |
# FIXME: (jany) looks inefficient | |
if isinstance(key, basestring): | |
# by glyph name | |
@@ -571,6 +630,7 @@ | |
return None | |
def values(self): | |
+ # type: () -> List[GSGlyph] | |
return self._owner._glyphs | |
def items(self): | |
@@ -581,6 +641,7 @@ | |
return items | |
def append(self, glyph): | |
+ # type: (GSGlyph) -> None | |
self._owner._setupGlyph(glyph) | |
self._owner._glyphs.append(glyph) | |
@@ -590,9 +651,11 @@ | |
self._owner._glyphs.extend(list(objects)) | |
def __len__(self): | |
+ # type: () -> int | |
return len(self._owner._glyphs) | |
def setter(self, values): | |
+ # type: (List[GSGlyph]) -> None | |
if isinstance(values, Proxy): | |
values = list(values) | |
self._owner._glyphs = values | |
@@ -608,6 +671,7 @@ | |
class FontClassesProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (Union[int, str]) -> GSClass | |
if isinstance(key, (slice, int)): | |
return self.values().__getitem__(key) | |
if isinstance(key, (str, unicode)): | |
@@ -629,6 +693,7 @@ | |
raise KeyError | |
def __delitem__(self, key): | |
+ # type: (str) -> None | |
if isinstance(key, int): | |
del self.values()[key] | |
elif isinstance(key, (str, unicode)): | |
@@ -639,25 +704,31 @@ | |
# FIXME: (jany) def __contains__ | |
def append(self, item): | |
+ # type: (GSClass) -> None | |
self.values().append(item) | |
item._parent = self._owner | |
def insert(self, key, item): | |
+ # type: (int, GSClass) -> None | |
self.values().insert(key, item) | |
item._parent = self._owner | |
def extend(self, items): | |
+ # type: (List[GSClass]) -> None | |
self.values().extend(items) | |
for value in items: | |
value._parent = self._owner | |
def remove(self, item): | |
+ # type: (GSClass) -> None | |
self.values().remove(item) | |
def values(self): | |
+ # type: () -> List[GSClass] | |
return self._owner._classes | |
def setter(self, values): | |
+ # type: (List[GSClass]) -> None | |
if isinstance(values, Proxy): | |
values = list(values) | |
self._owner._classes = values | |
@@ -667,6 +738,7 @@ | |
class GlyphLayerProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (Union[int, str]) -> Optional[GSLayer] | |
self._ensureMasterLayers() | |
if isinstance(key, slice): | |
return self.values().__getitem__(key) | |
@@ -679,6 +751,7 @@ | |
return self._owner._layers[key] | |
def __setitem__(self, key, layer): | |
+ # type: (str, GSLayer) -> None | |
if isinstance(key, int) and self._owner.parent: | |
OldLayer = self._owner._layers.values()[key] | |
if key < 0: | |
@@ -695,6 +768,7 @@ | |
raise KeyError | |
def __delitem__(self, key): | |
+ # type: (int) -> None | |
if isinstance(key, int) and self._owner.parent: | |
if key < 0: | |
key = self.__len__() + key | |
@@ -703,20 +777,25 @@ | |
del(self._owner._layers[key]) | |
def __iter__(self): | |
+ # type: () -> LayersIterator | |
return LayersIterator(self._owner) | |
def __len__(self): | |
+ # type: () -> int | |
return len(self.values()) | |
def keys(self): | |
+ # type: () -> odict_keys | |
self._ensureMasterLayers() | |
return self._owner._layers.keys() | |
def values(self): | |
+ # type: () -> odict_values | |
self._ensureMasterLayers() | |
return self._owner._layers.values() | |
def append(self, layer): | |
+ # type: (GSLayer) -> None | |
assert layer is not None | |
self._ensureMasterLayers() | |
if not layer.associatedMasterId: | |
@@ -728,17 +807,21 @@ | |
self._owner._layers[layer.layerId] = layer | |
def extend(self, layers): | |
+ # type: (List[GSLayer]) -> None | |
for layer in layers: | |
self.append(layer) | |
def remove(self, layer): | |
+ # type: (GSLayer) -> Optional[Any] | |
return self._owner.removeLayerForKey_(layer.layerId) | |
def insert(self, index, layer): | |
+ # type: (int, GSLayer) -> None | |
self._ensureMasterLayers() | |
self.append(layer) | |
def setter(self, values): | |
+ # type: (List[GSLayer]) -> None | |
newLayers = OrderedDict() | |
if (type(values) == list or | |
type(values) == tuple or | |
@@ -755,6 +838,7 @@ | |
self._owner._layers = newLayers | |
def _ensureMasterLayers(self): | |
+ # type: () -> None | |
# Ensure existence of master-linked layers (even for iteration, len() etc.) if accidentally deleted | |
if not self._owner.parent: | |
return | |
@@ -769,12 +853,14 @@ | |
self.__setitem__(master.id, newLayer) | |
def plistArray(self): | |
+ # type: () -> List[GSLayer] | |
return list(self._owner._layers.values()) | |
class LayerAnchorsProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (Union[int, str]) -> GSAnchor | |
if isinstance(key, (slice, int)): | |
return self.values().__getitem__(key) | |
elif isinstance(key, (str, unicode)): | |
@@ -785,6 +871,7 @@ | |
raise KeyError | |
def __setitem__(self, key, anchor): | |
+ # type: (str, GSAnchor) -> None | |
if isinstance(key, (str, unicode)): | |
anchor.name = key | |
for i, a in enumerate(self._owner._anchors): | |
@@ -797,6 +884,7 @@ | |
raise TypeError | |
def __delitem__(self, key): | |
+ # type: (str) -> None | |
if isinstance(key, int): | |
del self._owner._anchors[key] | |
elif isinstance(key, (str, unicode)): | |
@@ -807,9 +895,11 @@ | |
return | |
def values(self): | |
+ # type: () -> List[GSAnchor] | |
return self._owner._anchors | |
def append(self, anchor): | |
+ # type: (GSAnchor) -> None | |
for i, a in enumerate(self._owner._anchors): | |
if a.name == anchor.name: | |
anchor._parent = self._owner | |
@@ -821,11 +911,13 @@ | |
raise ValueError("Anchor must have name") | |
def extend(self, anchors): | |
+ # type: (List[GSAnchor]) -> None | |
for anchor in anchors: | |
anchor._parent = self._owner | |
self._owner._anchors.extend(anchors) | |
def remove(self, anchor): | |
+ # type: (GSAnchor) -> Optional[Any] | |
if isinstance(anchor, (str, unicode)): | |
anchor = self.values()[anchor] | |
return self._owner._anchors.remove(anchor) | |
@@ -835,9 +927,11 @@ | |
self._owner._anchors.insert(index, anchor) | |
def __len__(self): | |
+ # type: () -> int | |
return len(self._owner._anchors) | |
def setter(self, anchors): | |
+ # type: (Union[List[GSAnchor], LayerAnchorsProxy]) -> None | |
if isinstance(anchors, Proxy): | |
anchors = list(anchors) | |
self._owner._anchors = anchors | |
@@ -847,6 +941,7 @@ | |
class IndexedObjectsProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (Union[int, slice]) -> Any | |
if isinstance(key, (slice, int)): | |
return self.values().__getitem__(key) | |
else: | |
@@ -860,34 +955,42 @@ | |
raise KeyError | |
def __delitem__(self, key): | |
+ # type: (int) -> None | |
if isinstance(key, int): | |
del self.values()[key] | |
else: | |
raise KeyError | |
def values(self): | |
+ # type: () -> Any | |
return getattr(self._owner, self._objects_name) | |
def append(self, value): | |
+ # type: (Any) -> None | |
self.values().append(value) | |
value._parent = self._owner | |
def extend(self, values): | |
+ # type: (Any) -> None | |
self.values().extend(values) | |
for value in values: | |
value._parent = self._owner | |
def remove(self, value): | |
+ # type: (Any) -> None | |
self.values().remove(value) | |
def insert(self, index, value): | |
+ # type: (int, Any) -> None | |
self.values().insert(index, value) | |
value._parent = self._owner | |
def __len__(self): | |
+ # type: () -> int | |
return len(self.values()) | |
def setter(self, values): | |
+ # type: (Union[List[GSComponent], List[GSNode], List[GSPath]]) -> None | |
setattr(self._owner, self._objects_name, list(values)) | |
for value in self.values(): | |
value._parent = self._owner | |
@@ -897,6 +1000,7 @@ | |
_objects_name = "_paths" | |
def __init__(self, owner): | |
+ # type: (Union[GSBackgroundLayer, GSLayer]) -> None | |
super(LayerPathsProxy, self).__init__(owner) | |
@@ -904,6 +1008,7 @@ | |
_objects_name = "_hints" | |
def __init__(self, owner): | |
+ # type: (Union[GSBackgroundLayer, GSLayer]) -> None | |
super(LayerHintsProxy, self).__init__(owner) | |
@@ -911,6 +1016,7 @@ | |
_objects_name = "_components" | |
def __init__(self, owner): | |
+ # type: (Union[GSBackgroundLayer, GSLayer]) -> None | |
super(LayerComponentsProxy, self).__init__(owner) | |
@@ -918,6 +1024,7 @@ | |
_objects_name = "_annotations" | |
def __init__(self, owner): | |
+ # type: (Union[GSBackgroundLayer, GSLayer]) -> None | |
super(LayerAnnotationProxy, self).__init__(owner) | |
@@ -925,6 +1032,7 @@ | |
_objects_name = "_guides" | |
def __init__(self, owner): | |
+ # type: (Union[GSBackgroundLayer, GSLayer]) -> None | |
super(LayerGuideLinesProxy, self).__init__(owner) | |
@@ -932,11 +1040,13 @@ | |
_objects_name = "_nodes" | |
def __init__(self, owner): | |
+ # type: (GSPath) -> None | |
super(PathNodesProxy, self).__init__(owner) | |
class CustomParametersProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (str) -> Any | |
if isinstance(key, slice): | |
return self.values().__getitem__(key) | |
if isinstance(key, int): | |
@@ -948,11 +1058,13 @@ | |
return None | |
def _get_parameter_by_key(self, key): | |
+ # type: (str) -> Optional[GSCustomParameter] | |
for customParameter in self._owner._customParameters: | |
if customParameter.name == key: | |
return customParameter | |
def __setitem__(self, key, value): | |
+ # type: (str, Any) -> None | |
customParameter = self._get_parameter_by_key(key) | |
if customParameter is not None: | |
customParameter.value = value | |
@@ -961,6 +1073,7 @@ | |
self._owner._customParameters.append(parameter) | |
def __delitem__(self, key): | |
+ # type: (Union[int, str]) -> None | |
if isinstance(key, int): | |
del self._owner._customParameters[key] | |
elif isinstance(key, basestring): | |
@@ -971,50 +1084,60 @@ | |
raise KeyError | |
def __contains__(self, item): | |
+ # type: (str) -> bool | |
if isString(item): | |
return self.__getitem__(item) is not None | |
return item in self._owner._customParameters | |
def __iter__(self): | |
+ # type: () -> Iterator[Union[Iterator, Iterator[GSCustomParameter]]] | |
for index in range(len(self._owner._customParameters)): | |
yield self._owner._customParameters[index] | |
def append(self, parameter): | |
+ # type: (GSCustomParameter) -> None | |
parameter.parent = self._owner | |
self._owner._customParameters.append(parameter) | |
def extend(self, parameters): | |
+ # type: (List[GSCustomParameter]) -> None | |
for parameter in parameters: | |
parameter.parent = self._owner | |
self._owner._customParameters.extend(parameters) | |
def remove(self, parameter): | |
+ # type: (GSCustomParameter) -> None | |
if isString(parameter): | |
parameter = self.__getitem__(parameter) | |
self._owner._customParameters.remove(parameter) | |
def insert(self, index, parameter): | |
+ # type: (int, GSCustomParameter) -> None | |
parameter.parent = self._owner | |
self._owner._customParameters.insert(index, parameter) | |
def __len__(self): | |
+ # type: () -> int | |
return len(self._owner._customParameters) | |
def values(self): | |
return self._owner._customParameters | |
def __setter__(self, parameters): | |
+ # type: (List[GSCustomParameter]) -> None | |
for parameter in parameters: | |
parameter.parent = self._owner | |
self._owner._customParameters = parameters | |
def setterMethod(self): | |
+ # type: () -> Callable | |
return self.__setter__ | |
class UserDataProxy(Proxy): | |
def __getitem__(self, key): | |
+ # type: (str) -> Any | |
if self._owner._userData is None: | |
return None | |
# This is not the normal `dict` behaviour, because this does not raise | |
@@ -1022,16 +1145,19 @@ | |
return self._owner._userData.get(key) | |
def __setitem__(self, key, value): | |
+ # type: (str, Any) -> None | |
if self._owner._userData is not None: | |
self._owner._userData[key] = value | |
else: | |
self._owner._userData = {key: value} | |
def __delitem__(self, key): | |
+ # type: (str) -> None | |
if self._owner._userData is not None and key in self._owner._userData: | |
del self._owner._userData[key] | |
def __contains__(self, item): | |
+ # type: (str) -> bool | |
if self._owner._userData is None: | |
return False | |
return item in self._owner._userData | |
@@ -1045,21 +1171,25 @@ | |
yield value | |
def values(self): | |
+ # type: () -> Union[List, dict_values] | |
if self._owner._userData is None: | |
return [] | |
return self._owner._userData.values() | |
def keys(self): | |
+ # type: () -> Union[List, dict_keys, odict_keys] | |
if self._owner._userData is None: | |
return [] | |
return self._owner._userData.keys() | |
def get(self, key): | |
+ # type: (str) -> Optional[Dict[str, List[str]]] | |
if self._owner._userData is None: | |
return None | |
return self._owner._userData.get(key) | |
def setter(self, values): | |
+ # type: (Dict[str, Any]) -> None | |
self._owner._userData = values | |
@@ -1116,6 +1246,7 @@ | |
'GASP Table')) | |
def __init__(self, name="New Value", value="New Parameter"): | |
+ # type: (str, Any) -> None | |
self.name = name | |
self.value = value | |
@@ -1124,15 +1255,18 @@ | |
(self.__class__.__name__, self.name, self._value) | |
def plistValue(self): | |
+ # type: () -> str | |
string = UnicodeIO() | |
writer = Writer(string) | |
writer.writeDict({'name': self.name, 'value': self.value}) | |
return string.getvalue() | |
def getValue(self): | |
+ # type: () -> Any | |
return self._value | |
def setValue(self, value): | |
+ # type: (Any) -> None | |
"""Cast some known data in custom parameters.""" | |
if self.name in self._CUSTOM_INT_PARAMS: | |
value = int(value) | |
@@ -1154,11 +1288,13 @@ | |
class GSAlignmentZone(GSBase): | |
def __init__(self, pos=0, size=20): | |
+ # type: (int, int) -> None | |
super(GSAlignmentZone, self).__init__() | |
self.position = pos | |
self.size = size | |
def read(self, src): | |
+ # type: (str) -> GSAlignmentZone | |
if src is not None: | |
p = Point(src) | |
self.position = float(p.value[0]) | |
@@ -1166,13 +1302,16 @@ | |
return self | |
def __repr__(self): | |
+ # type: () -> str | |
return "<%s pos:%g size:%g>" % \ | |
(self.__class__.__name__, self.position, self.size) | |
def __lt__(self, other): | |
+ # type: (GSAlignmentZone) -> bool | |
return (self.position, self.size) < (other.position, other.size) | |
def plistValue(self): | |
+ # type: () -> str | |
return '"{%s, %s}"' % \ | |
(floatToString(self.position), floatToString(self.size)) | |
@@ -1193,15 +1332,18 @@ | |
} | |
def __init__(self): | |
+ # type: () -> None | |
super(GSGuideLine, self).__init__() | |
def __repr__(self): | |
+ # type: () -> str | |
return "<%s x=%.1f y=%.1f angle=%.1f>" % \ | |
(self.__class__.__name__, self.position.x, self.position.y, | |
self.angle) | |
@property | |
def parent(self): | |
+ # type: () -> GSLayer | |
return self._parent | |
@@ -1286,6 +1428,7 @@ | |
) | |
def __init__(self): | |
+ # type: () -> None | |
super(GSFontMaster, self).__init__() | |
self.id = str(uuid.uuid4()) | |
self.font = None | |
@@ -1298,10 +1441,12 @@ | |
setattr(self, 'customValue' + number, 0.0) | |
def __repr__(self): | |
+ # type: () -> str | |
return '<GSFontMaster "%s" width %s weight %s>' % \ | |
(self.name, self.widthValue, self.weightValue) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key in ("weight", "width"): | |
return getattr(self, key) != "Regular" | |
if key in ("xHeight", "capHeight", "ascender", "descender"): | |
@@ -1314,6 +1459,7 @@ | |
@property | |
def name(self): | |
+ # type: () -> str | |
name = self.customParameters['Master Name'] | |
if name: | |
return name | |
@@ -1323,6 +1469,7 @@ | |
@name.setter | |
def name(self, name): | |
+ # type: (str) -> None | |
"""This function will take the given name and split it into components | |
weight, width, customName, and possibly the full name. | |
This is what Glyphs 1113 seems to be doing, approximately. | |
@@ -1330,7 +1477,13 @@ | |
weight, width, custom_name = self._splitName(name) | |
self.set_all_name_components(name, weight, width, custom_name) | |
- def set_all_name_components(self, name, weight, width, custom_name): | |
+ def set_all_name_components(self, | |
+ name, # type: Optional[str] | |
+ weight, # type: Optional[str] | |
+ width, # type: Optional[str] | |
+ custom_name, # type: Optional[str] | |
+ ): | |
+ # type: (...) -> None | |
"""This function ensures that after being called, the master.name, | |
master.weight, master.width, and master.customName match the given | |
values. | |
@@ -1347,6 +1500,7 @@ | |
self.customParameters['Master Name'] = name | |
def _joinName(self): | |
+ # type: () -> str | |
names = [self.width, self.weight, self.customName] | |
names = [n for n in names if n] # Remove None and empty string | |
# Remove all occurences of 'Regular' | |
@@ -1357,6 +1511,7 @@ | |
return " ".join(list(names)) | |
def _splitName(self, value): | |
+ # type: (str) -> Tuple[str, str, str] | |
if value is None: | |
value = '' | |
weight = 'Regular' | |
@@ -1407,6 +1562,7 @@ | |
def __init__(self, position=(0, 0), nodetype=LINE, | |
smooth=False, name=None): | |
+ # type: (Union[Tuple[int, int], Point], str, bool, None) -> None | |
super(GSNode, self).__init__() | |
self.position = Point(position[0], position[1]) | |
self.type = nodetype | |
@@ -1416,6 +1572,7 @@ | |
self.name = name | |
def __repr__(self): | |
+ # type: () -> str | |
content = self.type | |
if self.smooth: | |
content += " smooth" | |
@@ -1429,9 +1586,11 @@ | |
@property | |
def parent(self): | |
+ # type: () -> GSPath | |
return self._parent | |
def plistValue(self): | |
+ # type: () -> str | |
content = self.type.upper() | |
if self.smooth: | |
content += " SMOOTH" | |
@@ -1446,6 +1605,7 @@ | |
content) | |
def read(self, line): | |
+ # type: (str) -> GSNode | |
m = self._PLIST_VALUE_RE.match(line).groups() | |
self.position = Point(float(m[0]), float(m[1])) | |
self.type = m[2].lower() | |
@@ -1460,12 +1620,14 @@ | |
@property | |
def name(self): | |
+ # type: () -> str | |
if "name" in self.userData: | |
return self.userData["name"] | |
return None | |
@name.setter | |
def name(self, value): | |
+ # type: (Optional[str]) -> None | |
if value is None: | |
if "name" in self.userData: | |
del(self.userData["name"]) | |
@@ -1474,11 +1636,13 @@ | |
@property | |
def index(self): | |
+ # type: () -> int | |
assert self.parent | |
return self.parent.nodes.index(self) | |
@property | |
def nextNode(self): | |
+ # type: () -> GSNode | |
assert self.parent | |
index = self.index | |
if index == (len(self.parent.nodes) - 1): | |
@@ -1488,6 +1652,7 @@ | |
@property | |
def prevNode(self): | |
+ # type: () -> GSNode | |
assert self.parent | |
index = self.index | |
if index == 0: | |
@@ -1496,6 +1661,7 @@ | |
return self.parent.nodes[index - 1] | |
def makeNodeFirst(self): | |
+ # type: () -> None | |
assert self.parent | |
if self.type == 'offcurve': | |
raise ValueError('Off-curve points cannot become start points.') | |
@@ -1505,6 +1671,7 @@ | |
self.parent.nodes = newNodes | |
def toggleConnection(self): | |
+ # type: () -> None | |
self.smooth = not self.smooth | |
# TODO | |
@@ -1518,6 +1685,7 @@ | |
raise OnlyInGlyphsAppError | |
def _encode_dict_as_string(self, value): | |
+ # type: (str) -> str | |
"""Takes the PLIST string of a dict, and returns the same string | |
encoded such that it can be included in the string representation | |
of a GSNode.""" | |
@@ -1534,6 +1702,7 @@ | |
@staticmethod | |
def _unescape_char(m): | |
+ # type: (SRE_Match) -> str | |
char = m.group(1) | |
if char == '\\': | |
return '\\' | |
@@ -1544,10 +1713,12 @@ | |
return m.group(0) | |
def _decode_dict_as_string(self, value): | |
+ # type: (str) -> str | |
"""Reverse function of _encode_string_as_dict""" | |
return self._ESCAPED_CHAR_RE.sub(self._unescape_char, value) | |
def _indices(self): | |
+ # type: () -> Point | |
"""Find the path_index and node_index that identify the given node.""" | |
path = self.parent | |
layer = path.parent | |
@@ -1570,14 +1741,17 @@ | |
_parent = None | |
def __init__(self): | |
+ # type: () -> None | |
super(GSPath, self).__init__() | |
self.nodes = [] | |
@property | |
def parent(self): | |
+ # type: () -> Union[GSBackgroundLayer, GSLayer] | |
return self._parent | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == "closed": | |
return True | |
return super(GSPath, self).shouldWriteValueForKey(key) | |
@@ -1588,6 +1762,7 @@ | |
@property | |
def segments(self): | |
+ # type: () -> List[segment] | |
self._segments = [] | |
self._segmentLength = 0 | |
@@ -1627,6 +1802,7 @@ | |
raise TypeError | |
def setSegments(self, segments): | |
+ # type: (List[segment]) -> None | |
self.nodes = [] | |
for segment in segments: | |
if len(segment.nodes) == 2 or len(segment.nodes) == 4: | |
@@ -1636,6 +1812,7 @@ | |
@property | |
def bounds(self): | |
+ # type: () -> Rect | |
left, bottom, right, top = None, None, None, None | |
for segment in self.segments: | |
newLeft, newBottom, newRight, newTop = segment.bbox() | |
@@ -1659,6 +1836,7 @@ | |
@property | |
def direction(self): | |
+ # type: () -> int | |
direction = 0 | |
for i in range(len(self.nodes)): | |
thisNode = self.nodes[i] | |
@@ -1678,6 +1856,7 @@ | |
raise OnlyInGlyphsAppError | |
def reverse(self): | |
+ # type: () -> None | |
segments = list(reversed(self.segments)) | |
for s, segment in enumerate(segments): | |
segment.nodes = list(reversed(segment.nodes)) | |
@@ -1721,6 +1900,7 @@ | |
class segment(list): | |
def appendNode(self, node): | |
+ # type: (GSNode) -> None | |
if not hasattr(self, 'nodes'): # instead of defining this in __init__(), because I hate super() | |
self.nodes = [] | |
self.nodes.append(node) | |
@@ -1745,6 +1925,7 @@ | |
return self.parent._segments[index - 1] | |
def bbox(self): | |
+ # type: () -> Tuple[float, float, float, float] | |
if len(self) == 2: | |
left = min(self[0].x, self[1].x) | |
bottom = min(self[0].y, self[1].y) | |
@@ -1757,7 +1938,17 @@ | |
else: | |
raise ValueError | |
- def bezierMinMax(self, x0, y0, x1, y1, x2, y2, x3, y3): | |
+ def bezierMinMax(self, | |
+ x0, # type: float | |
+ y0, # type: float | |
+ x1, # type: float | |
+ y1, # type: float | |
+ x2, # type: float | |
+ y2, # type: float | |
+ x3, # type: float | |
+ y3, # type: float | |
+ ): | |
+ # type: (...) -> Tuple[float, float, float, float] | |
tvalues = [] | |
xvalues = [] | |
yvalues = [] | |
@@ -1832,6 +2023,7 @@ | |
# TODO: glyph arg is required | |
def __init__(self, glyph="", offset=(0, 0), scale=(1, 1), transform=None): | |
+ # type: (str, Tuple[int, int], Tuple[int, int], None) -> None | |
super(GSComponent, self).__init__() | |
if transform is None: | |
@@ -1848,10 +2040,12 @@ | |
self.name = glyph.name | |
def __repr__(self): | |
+ # type: () -> str | |
return '<GSComponent "%s" x=%.1f y=%.1f>' % \ | |
(self.name, self.transform[4], self.transform[5]) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == "piece": | |
value = self.smartComponentValues | |
return len(value) > 0 | |
@@ -1859,24 +2053,29 @@ | |
@property | |
def parent(self): | |
+ # type: () -> GSLayer | |
return self._parent | |
# .position | |
@property | |
def position(self): | |
+ # type: () -> Point | |
return Point(self.transform[4], self.transform[5]) | |
@position.setter | |
def position(self, value): | |
+ # type: (Point) -> None | |
self.transform[4] = value[0] | |
self.transform[5] = value[1] | |
# .scale | |
@property | |
def scale(self): | |
+ # type: () -> Tuple[float, float] | |
self._sX, self._sY, self._R = transformStructToScaleAndRotation(self.transform.value) | |
return (self._sX, self._sY) | |
@scale.setter | |
def scale(self, value): | |
+ # type: (float) -> None | |
self._sX, self._sY, self._R = transformStructToScaleAndRotation(self.transform.value) | |
if type(value) in [int, float]: | |
self._sX = value | |
@@ -1890,20 +2089,24 @@ | |
# .rotation | |
@property | |
def rotation(self): | |
+ # type: () -> float | |
self._sX, self._sY, self._R = transformStructToScaleAndRotation(self.transform.value) | |
return self._R | |
@rotation.setter | |
def rotation(self, value): | |
+ # type: (int) -> None | |
self._sX, self._sY, self._R = transformStructToScaleAndRotation(self.transform.value) | |
self._R = value | |
self.updateAffineTransform() | |
def updateAffineTransform(self): | |
+ # type: () -> None | |
affine = list(Affine.translation(self.transform[4], self.transform[5]) * Affine.scale(self._sX, self._sY) * Affine.rotation(self._R))[:6] | |
self.transform = Transform(affine[0], affine[1], affine[3], affine[4], affine[2], affine[5]) | |
@property | |
def componentName(self): | |
+ # type: () -> str | |
return self.name | |
@componentName.setter | |
def componentName(self, value): | |
@@ -1911,13 +2114,16 @@ | |
@property | |
def component(self): | |
+ # type: () -> GSGlyph | |
return self.parent.parent.parent.glyphs[self.name] | |
@property | |
def layer(self): | |
+ # type: () -> GSLayer | |
return self.parent.parent.parent.glyphs[self.name].layers[self.parent.layerId] | |
def applyTransformation(self, x, y): | |
+ # type: (float, float) -> Tuple[float, float] | |
x *= self.scale[0] | |
y *= self.scale[1] | |
x += self.position.x | |
@@ -1928,6 +2134,7 @@ | |
@property | |
def bounds(self): | |
+ # type: () -> Rect | |
bounds = self.layer.bounds | |
if bounds is not None: | |
left, bottom, width, height = self.layer.bounds | |
@@ -1962,6 +2169,7 @@ | |
) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key in ("bottomValue", "topValue"): | |
return True | |
return super(GSSmartComponentAxis, self).shouldWriteValueForKey(key) | |
@@ -1978,6 +2186,7 @@ | |
} | |
def __init__(self, name=None, position=None): | |
+ # type: (Optional[str], Optional[Point]) -> None | |
super(GSAnchor, self).__init__() | |
if name is not None: | |
self.name = name | |
@@ -1985,17 +2194,20 @@ | |
self.position = position | |
def __repr__(self): | |
+ # type: () -> str | |
return '<%s "%s" x=%.1f y=%.1f>' % \ | |
(self.__class__.__name__, self.name, self.position[0], | |
self.position[1]) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == 'position': | |
return True | |
return super(GSAnchor, self).shouldWriteValueForKey(key) | |
@property | |
def parent(self): | |
+ # type: () -> GSLayer | |
return self._parent | |
@@ -2039,6 +2251,7 @@ | |
) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == "settings" and (self.settings is None or len(self.settings) == 0): | |
return None | |
return super(GSHint, self).shouldWriteValueForKey(key) | |
@@ -2060,6 +2273,7 @@ | |
return self.width | |
def __repr__(self): | |
+ # type: () -> str | |
if self.horizontal: | |
direction = "horizontal" | |
else: | |
@@ -2076,10 +2290,12 @@ | |
@property | |
def parent(self): | |
+ # type: () -> GSLayer | |
return self._parent | |
@property | |
def originNode(self): | |
+ # type: () -> GSNode | |
if self._originNode is not None: | |
return self._originNode | |
if self._origin is not None: | |
@@ -2087,11 +2303,13 @@ | |
@originNode.setter | |
def originNode(self, node): | |
+ # type: (GSNode) -> None | |
self._originNode = node | |
self._origin = None | |
@property | |
def origin(self): | |
+ # type: () -> Optional[Point] | |
if self._origin is not None: | |
return self._origin | |
if self._originNode is not None: | |
@@ -2099,11 +2317,13 @@ | |
@origin.setter | |
def origin(self, origin): | |
+ # type: (Optional[Point]) -> None | |
self._origin = origin | |
self._originNode = None | |
@property | |
def targetNode(self): | |
+ # type: () -> GSNode | |
if self._targetNode is not None: | |
return self._targetNode | |
if self._target is not None: | |
@@ -2111,11 +2331,13 @@ | |
@targetNode.setter | |
def targetNode(self, node): | |
+ # type: (GSNode) -> None | |
self._targetNode = node | |
self._target = None | |
@property | |
def target(self): | |
+ # type: () -> Optional[Point] | |
if self._target is not None: | |
return self._target | |
if self._targetNode is not None: | |
@@ -2123,6 +2345,7 @@ | |
@target.setter | |
def target(self, target): | |
+ # type: (Optional[Point]) -> None | |
self._target = target | |
self._targetNode = None | |
@@ -2135,11 +2358,13 @@ | |
@otherNode1.setter | |
def otherNode1(self, node): | |
+ # type: (GSNode) -> None | |
self._otherNode1 = node | |
self._other1 = None | |
@property | |
def other1(self): | |
+ # type: () -> Optional[Point] | |
if self._other1 is not None: | |
return self._other1 | |
if self._otherNode1 is not None: | |
@@ -2147,6 +2372,7 @@ | |
@other1.setter | |
def other1(self, other1): | |
+ # type: (None) -> None | |
self._other1 = other1 | |
self._otherNode1 = None | |
@@ -2159,11 +2385,13 @@ | |
@otherNode2.setter | |
def otherNode2(self, node): | |
+ # type: (GSNode) -> None | |
self._otherNode2 = node | |
self._other2 = None | |
@property | |
def other2(self): | |
+ # type: () -> Optional[Point] | |
if self._other2 is not None: | |
return self._other2 | |
if self._otherNode2 is not None: | |
@@ -2171,6 +2399,7 @@ | |
@other2.setter | |
def other2(self, other2): | |
+ # type: (None) -> None | |
self._other2 = other2 | |
self._otherNode2 = None | |
@@ -2185,19 +2414,23 @@ | |
} | |
def __init__(self, name="xxxx", code=""): | |
+ # type: (str, str) -> None | |
super(GSFeature, self).__init__() | |
self.name = name | |
self.code = code | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == "code": | |
return True | |
return super(GSFeature, self).shouldWriteValueForKey(key) | |
def getCode(self): | |
+ # type: () -> str | |
return self._code | |
def setCode(self, code): | |
+ # type: (str) -> None | |
replacements = ( | |
('\\012', '\n'), ('\\011', '\t'), ('\\U2018', "'"), | |
('\\U2019', "'"), ('\\U201C', '"'), ('\\U201D', '"')) | |
@@ -2207,6 +2440,7 @@ | |
code = property(getCode, setCode) | |
def __repr__(self): | |
+ # type: () -> str | |
return '<%s "%s">' % \ | |
(self.__class__.__name__, self.name) | |
@@ -2312,6 +2546,7 @@ | |
pass | |
def __init__(self): | |
+ # type: () -> None | |
super(GSInstance, self).__init__() | |
# TODO: (jany) review this and move as much as possible into | |
# "_defaultsForKey" | |
@@ -2329,15 +2564,18 @@ | |
@property | |
def exports(self): | |
+ # type: () -> bool | |
"""Deprecated alias for `active`, which is in the documentation.""" | |
return self.active | |
@exports.setter | |
def exports(self, value): | |
+ # type: (bool) -> None | |
self.active = value | |
@property | |
def familyName(self): | |
+ # type: () -> str | |
value = self.customParameters["familyName"] | |
if value: | |
return value | |
@@ -2345,10 +2583,12 @@ | |
@familyName.setter | |
def familyName(self, value): | |
+ # type: (str) -> None | |
self.customParameters["familyName"] = value | |
@property | |
def preferredFamily(self): | |
+ # type: () -> str | |
value = self.customParameters["preferredFamily"] | |
if value: | |
return value | |
@@ -2356,10 +2596,12 @@ | |
@preferredFamily.setter | |
def preferredFamily(self, value): | |
+ # type: (str) -> None | |
self.customParameters["preferredFamily"] = value | |
@property | |
def preferredSubfamilyName(self): | |
+ # type: () -> str | |
value = self.customParameters["preferredSubfamilyName"] | |
if value: | |
return value | |
@@ -2367,10 +2609,12 @@ | |
@preferredSubfamilyName.setter | |
def preferredSubfamilyName(self, value): | |
+ # type: (str) -> None | |
self.customParameters["preferredSubfamilyName"] = value | |
@property | |
def windowsFamily(self): | |
+ # type: () -> str | |
value = self.customParameters["styleMapFamilyName"] | |
if value: | |
return value | |
@@ -2381,10 +2625,12 @@ | |
@windowsFamily.setter | |
def windowsFamily(self, value): | |
+ # type: (str) -> None | |
self.customParameters["styleMapFamilyName"] = value | |
@property | |
def windowsStyle(self): | |
+ # type: () -> str | |
if self.name in ("Regular", "Bold", "Italic", "Bold Italic"): | |
return self.name | |
else: | |
@@ -2392,6 +2638,7 @@ | |
@property | |
def windowsLinkedToStyle(self): | |
+ # type: () -> str | |
value = self.linkStyle | |
return value | |
if self.name in ("Regular", "Bold", "Italic", "Bold Italic"): | |
@@ -2401,6 +2648,7 @@ | |
@property | |
def fontName(self): | |
+ # type: () -> str | |
value = self.customParameters["postscriptFontName"] | |
if value: | |
return value | |
@@ -2409,10 +2657,12 @@ | |
@fontName.setter | |
def fontName(self, value): | |
+ # type: (str) -> None | |
self.customParameters["postscriptFontName"] = value | |
@property | |
def fullName(self): | |
+ # type: () -> str | |
value = self.customParameters["postscriptFullName"] | |
if value: | |
return value | |
@@ -2420,6 +2670,7 @@ | |
@fullName.setter | |
def fullName(self, value): | |
+ # type: (str) -> None | |
self.customParameters["postscriptFullName"] = value | |
@@ -2440,6 +2691,7 @@ | |
} | |
def __init__(self, path=None): | |
+ # type: (Optional[str]) -> None | |
super(GSBackgroundImage, self).__init__() | |
self.imagePath = path | |
self._sX, self._sY, self._R = transformStructToScaleAndRotation(self.transform.value) | |
@@ -2450,9 +2702,11 @@ | |
# .path | |
@property | |
def path(self): | |
+ # type: () -> str | |
return self.imagePath | |
@path.setter | |
def path(self, value): | |
+ # type: (str) -> None | |
# FIXME: (jany) use posix pathnames here? | |
# FIXME: (jany) the following code must have never been tested. | |
# Also it would require to keep track of the parent for background | |
@@ -2465,18 +2719,22 @@ | |
# .position | |
@property | |
def position(self): | |
+ # type: (Point) -> Optional[Any] | |
return Point(self.transform[4], self.transform[5]) | |
@position.setter | |
def position(self, value): | |
+ # type: (Point) -> None | |
self.transform[4] = value[0] | |
self.transform[5] = value[1] | |
# .scale | |
@property | |
def scale(self): | |
+ # type: (Tuple[float, float]) -> Optional[Any] | |
return (self._sX, self._sY) | |
@scale.setter | |
def scale(self, value): | |
+ # type: (Tuple[float, float]) -> None | |
if type(value) in [int, float]: | |
self._sX = value | |
self._sY = value | |
@@ -2489,24 +2747,29 @@ | |
# .rotation | |
@property | |
def rotation(self): | |
+ # type: (float) -> Optional[Any] | |
return self._R | |
@rotation.setter | |
def rotation(self, value): | |
+ # type: (float) -> None | |
self._R = value | |
self.updateAffineTransform() | |
# .alpha | |
@property | |
def alpha(self): | |
+ # type: () -> int | |
return self._alpha | |
@alpha.setter | |
def alpha(self, value): | |
+ # type: (int) -> None | |
if not 10 <= value <= 100: | |
value = 50 | |
self._alpha = value | |
def updateAffineTransform(self): | |
+ # type: () -> None | |
affine = list(Affine.translation(self.transform[4], self.transform[5]) * Affine.scale(self._sX, self._sY) * Affine.rotation(self._R))[:6] | |
self.transform = Transform(affine[0], affine[1], affine[3], affine[4], affine[2], affine[5]) | |
@@ -2569,6 +2832,7 @@ | |
) | |
def __init__(self): | |
+ # type: () -> None | |
super(GSLayer, self).__init__() | |
self.parent = None | |
self._anchors = [] | |
@@ -2583,6 +2847,7 @@ | |
self.backgroundImage = None | |
def __repr__(self): | |
+ # type: () -> str | |
name = self.name | |
try: | |
# assert self.name | |
@@ -2602,10 +2867,12 @@ | |
@property | |
def layerId(self): | |
+ # type: () -> str | |
return self._layerId | |
@layerId.setter | |
def layerId(self, value): | |
+ # type: (str) -> None | |
self._layerId = value | |
# Update the layer map in the parent glyph, if any. | |
# The "hasattr" is here because this setter is called by the GSBase | |
@@ -2630,6 +2897,7 @@ | |
return master | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == "width": | |
return True | |
if key == "associatedMasterId": | |
@@ -2641,6 +2909,7 @@ | |
@property | |
def name(self): | |
+ # type: () -> str | |
if (self.associatedMasterId and | |
self.associatedMasterId == self.layerId and self.parent): | |
master = self.parent.parent.masterForId(self.associatedMasterId) | |
@@ -2650,6 +2919,7 @@ | |
@name.setter | |
def name(self, value): | |
+ # type: (str) -> None | |
self._name = value | |
anchors = property( | |
@@ -2682,16 +2952,19 @@ | |
@property | |
def smartComponentPoleMapping(self): | |
+ # type: () -> Union[Dict[str, int], Dict[str, str]] | |
if "PartSelection" not in self.userData: | |
self.userData["PartSelection"] = {} | |
return self.userData["PartSelection"] | |
@smartComponentPoleMapping.setter | |
def smartComponentPoleMapping(self, value): | |
+ # type: (Dict[str, int]) -> None | |
self.userData["PartSelection"] = value | |
@property | |
def bounds(self): | |
+ # type: () -> Rect | |
left, bottom, right, top = None, None, None, None | |
for item in self.paths.values() + self.components.values(): | |
@@ -2721,6 +2994,7 @@ | |
return Rect(Point(left, bottom), Point(right - left, top - bottom)) | |
def _find_node_by_indices(self, point): | |
+ # type: (Point) -> GSNode | |
""""Find the GSNode that is refered to by the given indices. | |
See GSNode::_indices() | |
@@ -2732,6 +3006,7 @@ | |
@property | |
def background(self): | |
+ # type: () -> GSBackgroundLayer | |
"""Only a getter on purpose. See the tests.""" | |
if self._background is None: | |
self._background = GSBackgroundLayer() | |
@@ -2742,26 +3017,31 @@ | |
# ::background? | |
@property | |
def hasBackground(self): | |
+ # type: () -> bool | |
return bool(self._background) | |
@property | |
def foreground(self): | |
+ # type: () -> NoReturn | |
"""Forbidden, and also forbidden to set it.""" | |
raise AttributeError | |
class GSBackgroundLayer(GSLayer): | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key == 'width': | |
return False | |
return super(GSBackgroundLayer, self).shouldWriteValueForKey(key) | |
@property | |
def background(self): | |
+ # type: () -> Optional[Any] | |
return None | |
@property | |
def foreground(self): | |
+ # type: () -> GSLayer | |
return self._foreground | |
# The width property of this class behaves like this in Glyphs: | |
@@ -2770,6 +3050,7 @@ | |
# Reproduce this behaviour here so that the roundtrip does not rely on it. | |
@property | |
def width(self): | |
+ # type: () -> float | |
return 600.0 | |
@width.setter | |
@@ -2856,6 +3137,7 @@ | |
) | |
def __init__(self, name=None): | |
+ # type: (Optional[str]) -> None | |
super(GSGlyph, self).__init__() | |
self._layers = OrderedDict() | |
self.name = name | |
@@ -2869,6 +3151,7 @@ | |
return '<GSGlyph "%s" with %s layers>' % (self.name, len(self.layers)) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key in ("script", "category", "subCategory"): | |
return getattr(self, key) is not None | |
return super(GSGlyph, self).shouldWriteValueForKey(key) | |
@@ -2877,6 +3160,7 @@ | |
lambda self, value: GlyphLayerProxy(self).setter(value)) | |
def _setupLayer(self, layer, key): | |
+ # type: (GSLayer, str) -> None | |
assert isinstance(key, (str, unicode)) | |
layer.parent = self | |
layer.layerId = key | |
@@ -2893,12 +3177,14 @@ | |
# self._layers[key] = layer | |
def removeLayerForKey_(self, key): | |
+ # type: (str) -> None | |
for layer in list(self._layers): | |
if layer == key: | |
del self._layers[key] | |
@property | |
def string(self): | |
+ # type: () -> str | |
if self.unicode: | |
return unichr(int(self.unicode, 16)) | |
@@ -2921,20 +3207,24 @@ | |
@property | |
def unicode(self): | |
+ # type: () -> Optional[str] | |
if self._unicodes: | |
return self._unicodes[0] | |
return None | |
@unicode.setter | |
def unicode(self, unicode): | |
+ # type: (str) -> None | |
self._unicodes = UnicodesList(unicode) | |
@property | |
def unicodes(self): | |
+ # type: () -> UnicodesList | |
return self._unicodes | |
@unicodes.setter | |
def unicodes(self, unicodes): | |
+ # type: (Union[List[str], UnicodesList]) -> None | |
self._unicodes = UnicodesList(unicodes) | |
@@ -2988,6 +3278,7 @@ | |
} | |
def __init__(self, path=None): | |
+ # type: (Union[None, WindowsPath, str]) -> None | |
super(GSFont, self).__init__() | |
self.familyName = "Unnamed font" | |
@@ -3021,14 +3312,17 @@ | |
master.font = self | |
def __repr__(self): | |
+ # type: () -> str | |
return "<%s \"%s\">" % (self.__class__.__name__, self.familyName) | |
def shouldWriteValueForKey(self, key): | |
+ # type: (str) -> bool | |
if key in ("unitsPerEm", "versionMajor", "versionMinor"): | |
return True | |
return super(GSFont, self).shouldWriteValueForKey(key) | |
def save(self, path=None): | |
+ # type: (str) -> None | |
if path is None: | |
if self.filepath: | |
path = self.filepath | |
@@ -3040,9 +3334,11 @@ | |
w.write(self) | |
def getVersionMinor(self): | |
+ # type: () -> int | |
return self._versionMinor | |
def setVersionMinor(self, value): | |
+ # type: (int) -> None | |
"""Ensure that the minor version number is between 0 and 999.""" | |
assert value >= 0 and value <= 999 | |
self._versionMinor = value | |
@@ -3053,6 +3349,7 @@ | |
lambda self, value: FontGlyphsProxy(self).setter(value)) | |
def _setupGlyph(self, glyph): | |
+ # type: (GSGlyph) -> None | |
glyph.parent = self | |
for layer in glyph.layers: | |
if (not hasattr(layer, "associatedMasterId") or | |
@@ -3062,10 +3359,12 @@ | |
@property | |
def features(self): | |
+ # type: () -> List[GSFeature] | |
return self._features | |
@features.setter | |
def features(self, value): | |
+ # type: (List[GSFeature]) -> None | |
# FIXME: (jany) why not use Proxy like every other attribute? | |
# FIXME: (jany) do the same for featurePrefixes? | |
self._features = value | |
@@ -3076,6 +3375,7 @@ | |
lambda self, value: FontFontMasterProxy(self).setter(value)) | |
def masterForId(self, key): | |
+ # type: (str) -> Optional[GSFontMaster] | |
for master in self._masters: | |
if master.id == key: | |
return master | |
@@ -3084,10 +3384,12 @@ | |
# FIXME: (jany) Why is this not a FontInstanceProxy? | |
@property | |
def instances(self): | |
+ # type: () -> List[GSInstance] | |
return self._instances | |
@instances.setter | |
def instances(self, value): | |
+ # type: (List[GSInstance]) -> None | |
self._instances = value | |
for i in self._instances: | |
i.parent = self | |
@@ -3106,10 +3408,12 @@ | |
@property | |
def kerning(self): | |
+ # type: () -> Union[Dict[str, OrderedDict], OrderedDict] | |
return self._kerning | |
@kerning.setter | |
def kerning(self, kerning): | |
+ # type: (Union[Dict[str, OrderedDict], OrderedDict]) -> None | |
self._kerning = kerning | |
for master_id, master_map in kerning.items(): | |
for left_glyph, glyph_map in master_map.items(): | |
@@ -3122,6 +3426,7 @@ | |
@property | |
def note(self): | |
+ # type: () -> str | |
value = self.customParameters["note"] | |
if value: | |
return value | |
@@ -3130,10 +3435,12 @@ | |
@note.setter | |
def note(self, value): | |
+ # type: (str) -> None | |
self.customParameters["note"] = value | |
@property | |
def gridLength(self): | |
+ # type: () -> NoReturn | |
if (self.gridSubDivisions > 0): | |
return self.grid / self.gridSubDivisions | |
else: | |
@@ -3152,6 +3459,7 @@ | |
def setKerningForPair(self, fontMasterId, leftKey, rightKey, value, | |
direction=LTR): | |
+ # type: (str, str, str, float, int) -> None | |
# TODO: (jany) understand and use the direction parameter | |
if not self._kerning: | |
self._kerning = {} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment