Skip to content

Commit

Permalink
Annotate and document segment.py (#769)
Browse files Browse the repository at this point in the history
* Add type annotation.

* Format fixes by ruff

---------

Co-authored-by: knutnergaard <[email protected]>
  • Loading branch information
knutnergaard and knutnergaard authored Nov 14, 2024
1 parent 193ed08 commit d7a22eb
Showing 1 changed file with 73 additions and 48 deletions.
121 changes: 73 additions & 48 deletions Lib/fontParts/base/segment.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,6 @@
from __future__ import annotations
from typing import TYPE_CHECKING, Any, Generator, List, Optional, Tuple, Union

from fontParts.base.errors import FontPartsError
from fontParts.base.base import (
BaseObject,
Expand All @@ -10,6 +13,18 @@
from fontParts.base import normalizers
from fontParts.base.deprecated import DeprecatedSegment, RemovedSegment
from fontParts.base.compatibility import SegmentCompatibilityReporter
from fontParts.base.annotations import (
CollectionType,
SextupleCollectionType,
IntFloatType,
)

if TYPE_CHECKING:
from fontParts.base.point import BasePoint
from fontParts.base.contour import BaseContour
from fontParts.base.glyph import BaseGlyph
from fontParts.base.layer import BaseLayer
from fontParts.base.font import BaseFont


class BaseSegment(
Expand All @@ -20,12 +35,12 @@ class BaseSegment(
DeprecatedSegment,
RemovedSegment,
):
def _setPoints(self, points):
def _setPoints(self, points: CollectionType[BasePoint]) -> None:
if hasattr(self, "_points"):
raise AssertionError("segment has points")
self._points = points

def _reprContents(self):
def _reprContents(self) -> List[str]:
contents = [
f"{self.type}",
]
Expand All @@ -44,16 +59,18 @@ def _reprContents(self):

# Contour

_contour = None
_contour: Optional[BaseContour] = None

contour = dynamicProperty("contour", "The segment's parent contour.")
contour: dynamicProperty = dynamicProperty(
"contour", "The segment's parent contour."
)

def _get_contour(self):
def _get_contour(self) -> Optional[BaseContour]:
if self._contour is None:
return None
return self._contour()

def _set_contour(self, contour):
def _set_contour(self, contour: Optional[BaseContour]) -> None:
if self._contour is not None:
raise AssertionError("contour for segment already set")
if contour is not None:
Expand All @@ -62,27 +79,27 @@ def _set_contour(self, contour):

# Glyph

glyph = dynamicProperty("glyph", "The segment's parent glyph.")
glyph: dynamicProperty = dynamicProperty("glyph", "The segment's parent glyph.")

def _get_glyph(self):
def _get_glyph(self) -> Optional[BaseGlyph]:
if self._contour is None:
return None
return self.contour.glyph

# Layer

layer = dynamicProperty("layer", "The segment's parent layer.")
layer: dynamicProperty = dynamicProperty("layer", "The segment's parent layer.")

def _get_layer(self):
def _get_layer(self) -> Optional[BaseLayer]:
if self._contour is None:
return None
return self.glyph.layer

# Font

font = dynamicProperty("font", "The segment's parent font.")
font: dynamicProperty = dynamicProperty("font", "The segment's parent font.")

def _get_font(self):
def _get_font(self) -> Optional[BaseFont]:
if self._contour is None:
return None
return self.glyph.font
Expand All @@ -91,7 +108,7 @@ def _get_font(self):
# Equality
# --------

def __eq__(self, other):
def __eq__(self, other: object) -> bool:
"""
The :meth:`BaseObject.__eq__` method can't be used here
because the :class:`BaseContour` implementation contructs
Expand All @@ -110,22 +127,22 @@ def __eq__(self, other):
# Identification
# --------------

index = dynamicProperty(
index: dynamicProperty = dynamicProperty(
"base_index",
(
"The index of the segment within the ordered "
"list of the parent contour's segments."
),
)

def _get_base_index(self):
def _get_base_index(self) -> Optional[int]:
if self.contour is None:
return None
value = self._get_index()
value = normalizers.normalizeIndex(value)
return value
normalizedValue = normalizers.normalizeIndex(value)
return normalizedValue

def _get_index(self):
def _get_index(self) -> int:
"""
Subclasses may override this method.
"""
Expand All @@ -137,21 +154,21 @@ def _get_index(self):
# Attributes
# ----------

type = dynamicProperty(
type: dynamicProperty = dynamicProperty(
"base_type",
("The segment type. The possible types are " "move, line, curve, qcurve."),
)

def _get_base_type(self):
def _get_base_type(self) -> str:
value = self._get_type()
value = normalizers.normalizeSegmentType(value)
return value

def _set_base_type(self, value):
def _set_base_type(self, value: str) -> None:
value = normalizers.normalizeSegmentType(value)
self._set_type(value)

def _get_type(self):
def _get_type(self) -> str:
"""
Subclasses may override this method.
"""
Expand All @@ -160,7 +177,7 @@ def _get_type(self):
return "qcurve"
return onCurve.type

def _set_type(self, newType):
def _set_type(self, newType: str) -> None:
"""
Subclasses may override this method.
"""
Expand Down Expand Up @@ -200,20 +217,20 @@ def _set_type(self, newType):
self._setPoints((off1, off2, on))
self.onCurve.type = newType

smooth = dynamicProperty(
smooth: dynamicProperty = dynamicProperty(
"base_smooth", ("Boolean indicating if the segment is " "smooth or not.")
)

def _get_base_smooth(self):
def _get_base_smooth(self) -> bool:
value = self._get_smooth()
value = normalizers.normalizeBoolean(value)
return value

def _set_base_smooth(self, value):
def _set_base_smooth(self, value: bool) -> None:
value = normalizers.normalizeBoolean(value)
self._set_smooth(value)

def _get_smooth(self):
def _get_smooth(self) -> bool:
"""
Subclasses may override this method.
"""
Expand All @@ -222,7 +239,7 @@ def _get_smooth(self):
return True
return onCurve.smooth

def _set_smooth(self, value):
def _set_smooth(self, value: bool) -> None:
"""
Subclasses may override this method.
"""
Expand All @@ -234,10 +251,10 @@ def _set_smooth(self, value):
# Points
# ------

def __getitem__(self, index):
def __getitem__(self, index: int) -> BasePoint:
return self._getItem(index)

def _getItem(self, index):
def _getItem(self, index: int) -> BasePoint:
"""
Subclasses may override this method.
"""
Expand All @@ -246,7 +263,7 @@ def _getItem(self, index):
def __iter__(self):
return self._iterPoints()

def _iterPoints(self, **kwargs):
def _iterPoints(self, **kwargs: Any) -> Generator[BasePoint]:
"""
Subclasses may override this method.
"""
Expand All @@ -258,34 +275,38 @@ def _iterPoints(self, **kwargs):
count -= 1
index += 1

def __len__(self):
def __len__(self) -> int:
return self._len()

def _len(self, **kwargs):
def _len(self, **kwargs: Any) -> int:
"""
Subclasses may override this method.
"""
return len(self.points)

points = dynamicProperty("base_points", "A list of points in the segment.")
points: dynamicProperty = dynamicProperty(
"base_points", "A list of points in the segment."
)

def _get_base_points(self):
return tuple(self._get_points())
def _get_base_points(self) -> Tuple[BasePoint, ...]:
return self._get_points()

def _get_points(self):
def _get_points(self) -> Tuple[BasePoint, ...]:
"""
Subclasses may override this method.
"""
if not hasattr(self, "_points"):
return tuple()
return ()
return tuple(self._points)

onCurve = dynamicProperty("base_onCurve", "The on curve point in the segment.")
onCurve: dynamicProperty = dynamicProperty(
"base_onCurve", "The on curve point in the segment."
)

def _get_base_onCurve(self):
def _get_base_onCurve(self) -> Optional[BasePoint]:
return self._get_onCurve()

def _get_onCurve(self):
def _get_onCurve(self) -> Optional[BasePoint]:
"""
Subclasses may override this method.
"""
Expand All @@ -294,15 +315,17 @@ def _get_onCurve(self):
return None
return value

offCurve = dynamicProperty("base_offCurve", "The off curve points in the segment.")
offCurve: dynamicProperty = dynamicProperty(
"base_offCurve", "The off curve points in the segment."
)

def _get_base_offCurve(self):
def _get_base_offCurve(self) -> Tuple[BasePoint, ...]:
"""
Subclasses may override this method.
"""
return self._get_offCurve()

def _get_offCurve(self):
def _get_offCurve(self) -> Tuple[BasePoint, ...]:
"""
Subclasses may override this method.
"""
Expand All @@ -314,7 +337,7 @@ def _get_offCurve(self):
# Transformation
# --------------

def _transformBy(self, matrix, **kwargs):
def _transformBy(self, matrix: SextupleCollectionType[IntFloatType], **kwargs: Any):
"""
Subclasses may override this method.
"""
Expand All @@ -327,7 +350,7 @@ def _transformBy(self, matrix, **kwargs):

compatibilityReporterClass = SegmentCompatibilityReporter

def isCompatible(self, other):
def isCompatible(self, other: BaseSegment) -> Tuple[bool, str]:
"""
Evaluate interpolation compatibility with **other**. ::
Expand All @@ -346,7 +369,9 @@ def isCompatible(self, other):
"""
return super(BaseSegment, self).isCompatible(other, BaseSegment)

def _isCompatible(self, other, reporter):
def _isCompatible(
self, other: BaseSegment, reporter: SegmentCompatibilityReporter
) -> None:
"""
This is the environment implementation of
:meth:`BaseSegment.isCompatible`.
Expand All @@ -366,7 +391,7 @@ def _isCompatible(self, other, reporter):
# Misc
# ----

def round(self):
def round(self) -> None:
"""
Round coordinates in all points.
"""
Expand Down

0 comments on commit d7a22eb

Please sign in to comment.