From 33e45f2532af1c2158692382d60e5897effebd91 Mon Sep 17 00:00:00 2001 From: Ben Kiel Date: Fri, 1 Nov 2024 23:32:34 -0500 Subject: [PATCH] Ruff format codebase (#760) * update pyproject and add in github action for ruff * initial ruff formatting * Update pyproject.toml --- .github/workflows/ruff.yml | 20 + Lib/fontParts/__init__.py | 3 +- Lib/fontParts/base/anchor.py | 46 +- Lib/fontParts/base/annotations.py | 13 +- Lib/fontParts/base/bPoint.py | 96 +-- Lib/fontParts/base/base.py | 120 ++-- Lib/fontParts/base/color.py | 13 +- Lib/fontParts/base/compatibility.py | 147 +++-- Lib/fontParts/base/component.py | 62 +- Lib/fontParts/base/contour.py | 178 +++-- Lib/fontParts/base/deprecated.py | 341 +++++----- Lib/fontParts/base/features.py | 7 +- Lib/fontParts/base/font.py | 344 +++++----- Lib/fontParts/base/glyph.py | 613 ++++++++++-------- Lib/fontParts/base/groups.py | 10 +- Lib/fontParts/base/guideline.py | 41 +- Lib/fontParts/base/image.py | 33 +- Lib/fontParts/base/info.py | 52 +- Lib/fontParts/base/kerning.py | 75 ++- Lib/fontParts/base/layer.py | 108 +-- Lib/fontParts/base/lib.py | 1 - Lib/fontParts/base/normalizers.py | 465 +++++++------ Lib/fontParts/base/point.py | 59 +- Lib/fontParts/base/segment.py | 52 +- Lib/fontParts/fontshell/anchor.py | 1 - Lib/fontParts/fontshell/base.py | 1 - Lib/fontParts/fontshell/component.py | 1 - Lib/fontParts/fontshell/contour.py | 13 +- Lib/fontParts/fontshell/features.py | 1 - Lib/fontParts/fontshell/font.py | 19 +- Lib/fontParts/fontshell/glyph.py | 25 +- Lib/fontParts/fontshell/groups.py | 1 - Lib/fontParts/fontshell/guideline.py | 1 - Lib/fontParts/fontshell/image.py | 2 +- Lib/fontParts/fontshell/info.py | 1 - Lib/fontParts/fontshell/kerning.py | 1 - Lib/fontParts/fontshell/layer.py | 1 - Lib/fontParts/fontshell/lib.py | 1 - Lib/fontParts/fontshell/point.py | 13 +- Lib/fontParts/fontshell/test.py | 13 +- Lib/fontParts/test/__init__.py | 2 +- Lib/fontParts/test/legacyPointPen.py | 7 +- Lib/fontParts/test/test_anchor.py | 79 +-- Lib/fontParts/test/test_bPoint.py | 305 ++------- Lib/fontParts/test/test_color.py | 1 - Lib/fontParts/test/test_component.py | 320 +++------ Lib/fontParts/test/test_contour.py | 153 +---- Lib/fontParts/test/test_deprecated.py | 97 ++- Lib/fontParts/test/test_features.py | 46 +- Lib/fontParts/test/test_font.py | 218 ++----- Lib/fontParts/test/test_fuzzyNumber.py | 18 +- Lib/fontParts/test/test_glyph.py | 349 +++------- Lib/fontParts/test/test_groups.py | 133 +--- Lib/fontParts/test/test_guideline.py | 274 ++------ Lib/fontParts/test/test_image.py | 196 ++---- Lib/fontParts/test/test_info.py | 61 +- Lib/fontParts/test/test_kerning.py | 188 ++---- Lib/fontParts/test/test_layer.py | 104 +-- Lib/fontParts/test/test_lib.py | 68 +- Lib/fontParts/test/test_normalizers.py | 98 +-- Lib/fontParts/test/test_point.py | 286 ++------ Lib/fontParts/test/test_segment.py | 117 +--- Lib/fontParts/test/test_world.py | 58 +- Lib/fontParts/ui.py | 109 ++-- Lib/fontParts/world.py | 83 +-- .../_themes/fontPartsTheme/static/sass2css.py | 18 +- documentation/source/conf.py | 281 ++++---- documentation/tools/docstring.py | 427 ++++++------ pyproject.toml | 9 +- setup.py | 28 +- 70 files changed, 2975 insertions(+), 4152 deletions(-) create mode 100644 .github/workflows/ruff.yml diff --git a/.github/workflows/ruff.yml b/.github/workflows/ruff.yml new file mode 100644 index 00000000..95d0b0fe --- /dev/null +++ b/.github/workflows/ruff.yml @@ -0,0 +1,20 @@ +name: Ruff +on: [push, pull_request] +jobs: + ruff: + runs-on: ubuntu-latest + + permissions: + # Give the default GITHUB_TOKEN write permission to commit and push the + # added or changed files to the repository. + contents: write + + steps: + - uses: actions/checkout@v4 + - uses: astral-sh/ruff-action@v1 + with: + args: "format" + changed-files: "true" + - uses: stefanzweifel/git-auto-commit-action@v5 + with: + commit_message: 'Format fixes by ruff' diff --git a/Lib/fontParts/__init__.py b/Lib/fontParts/__init__.py index c00ae090..149ab937 100644 --- a/Lib/fontParts/__init__.py +++ b/Lib/fontParts/__init__.py @@ -3,6 +3,7 @@ except ImportError: try: from setuptools_scm import get_version + __version__ = get_version() except ImportError: - __version__ = 'unknown' + __version__ = "unknown" diff --git a/Lib/fontParts/base/anchor.py b/Lib/fontParts/base/anchor.py index fba0de58..60a74916 100644 --- a/Lib/fontParts/base/anchor.py +++ b/Lib/fontParts/base/anchor.py @@ -1,8 +1,14 @@ from fontTools.misc import transform from fontParts.base import normalizers from fontParts.base.base import ( - BaseObject, TransformationMixin, InterpolationMixin, SelectionMixin, - PointPositionMixin, IdentifierMixin, dynamicProperty, reference + BaseObject, + TransformationMixin, + InterpolationMixin, + SelectionMixin, + PointPositionMixin, + IdentifierMixin, + dynamicProperty, + reference, ) from fontParts.base.compatibility import AnchorCompatibilityReporter from fontParts.base.color import Color @@ -10,16 +16,15 @@ class BaseAnchor( - BaseObject, - TransformationMixin, - DeprecatedAnchor, - RemovedAnchor, - PointPositionMixin, - InterpolationMixin, - SelectionMixin, - IdentifierMixin - ): - + BaseObject, + TransformationMixin, + DeprecatedAnchor, + RemovedAnchor, + PointPositionMixin, + InterpolationMixin, + SelectionMixin, + IdentifierMixin, +): """ An anchor object. This object is almost always created with :meth:`BaseGlyph.appendAnchor`. @@ -42,12 +47,7 @@ def _reprContents(self): # Copy # ---- - copyAttributes = ( - "x", - "y", - "name", - "color" - ) + copyAttributes = ("x", "y", "name", "color") # ------- # Parents @@ -104,7 +104,7 @@ def _get_font(self): >>> anchor.x 100 >>> anchor.x = 101 - """ + """, ) def _get_base_x(self): @@ -147,7 +147,7 @@ def _set_x(self, value): >>> anchor.y 100 >>> anchor.y = 101 - """ + """, ) def _get_base_y(self): @@ -194,7 +194,7 @@ def _set_y(self, value): >>> anchor.index 0 - """ + """, ) def _get_base_index(self): @@ -225,7 +225,7 @@ def _get_index(self): >>> anchor.name 'my anchor' >>> anchor.name = None - """ + """, ) def _get_base_name(self): @@ -272,7 +272,7 @@ def _set_name(self, value): >>> anchor.color None >>> anchor.color = (1, 0, 0, 0.5) - """ + """, ) def _get_base_color(self): diff --git a/Lib/fontParts/base/annotations.py b/Lib/fontParts/base/annotations.py index 32b447d4..66a5b079 100644 --- a/Lib/fontParts/base/annotations.py +++ b/Lib/fontParts/base/annotations.py @@ -6,7 +6,7 @@ from fontTools.pens.pointPen import AbstractPointPen # Generic -T = TypeVar('T') +T = TypeVar("T") PairType = Tuple[T, T] QuadrupleType = Tuple[T, T, T, T] @@ -35,17 +35,14 @@ TransformationType = Union[IntFloatType, List[IntFloatType], PairType[IntFloatType]] # Interpolation -InterpolatableType = TypeVar('InterpolatableType', bound='Interpolatable') +InterpolatableType = TypeVar("InterpolatableType", bound="Interpolatable") class Interpolatable(Protocol): """Represent a protocol for interpolatable types.""" - def __add__(self, other: InterpolatableType) -> InterpolatableType: - ... + def __add__(self, other: InterpolatableType) -> InterpolatableType: ... - def __sub__(self, other: InterpolatableType) -> InterpolatableType: - ... + def __sub__(self, other: InterpolatableType) -> InterpolatableType: ... - def __mul__(self, other: TransformationType) -> InterpolatableType: - ... + def __mul__(self, other: TransformationType) -> InterpolatableType: ... diff --git a/Lib/fontParts/base/bPoint.py b/Lib/fontParts/base/bPoint.py index 9d93dee3..5dc2bd2f 100644 --- a/Lib/fontParts/base/bPoint.py +++ b/Lib/fontParts/base/bPoint.py @@ -8,7 +8,7 @@ SelectionMixin, IdentifierMixin, dynamicProperty, - reference + reference, ) from fontParts.base.errors import FontPartsError from fontParts.base import normalizers @@ -16,8 +16,9 @@ from fontParts.base.annotations import ( PairType, PairCollectionType, - SextupleCollectionType + SextupleCollectionType, ) + if TYPE_CHECKING: from fontParts.base.contour import BaseContour from fontParts.base.font import BaseFont @@ -27,12 +28,14 @@ from fontParts.base.segment import BaseSegment -class BaseBPoint(BaseObject, - TransformationMixin, - SelectionMixin, - DeprecatedBPoint, - IdentifierMixin, - RemovedBPoint): +class BaseBPoint( + BaseObject, + TransformationMixin, + SelectionMixin, + DeprecatedBPoint, + IdentifierMixin, + RemovedBPoint, +): """Represent the basis for a bPoint object.""" def _reprContents(self) -> List[str]: @@ -139,7 +142,7 @@ def _get_base_nextSegment(self) -> Optional[BaseSegment]: >>> contour = bPoint.contour - """ + """, ) def _get_contour(self) -> Optional[BaseContour]: @@ -171,7 +174,7 @@ def _set_contour(self, contour: Optional[BaseContour]) -> None: >>> glyph = bPoint.glyph - """ + """, ) def _get_glyph(self) -> Optional[BaseGlyph]: @@ -194,7 +197,7 @@ def _get_glyph(self) -> Optional[BaseGlyph]: >>> layer = bPoint.layer - """ + """, ) def _get_layer(self) -> Optional[BaseLayer]: @@ -217,7 +220,7 @@ def _get_layer(self) -> Optional[BaseLayer]: >>> font = bPoint.font - """ + """, ) def _get_font(self) -> Optional[BaseFont]: @@ -239,7 +242,7 @@ def _get_font(self) -> Optional[BaseFont]: :return: a :ref:`type-coordianate` representing the anchor point of the bPoint. - """ + """, ) def _get_base_anchor(self) -> PairType[IntFloatType]: @@ -301,7 +304,7 @@ def _set_anchor(self, value: PairCollectionType[IntFloatType]) -> None: :return: A :ref:`type-coordinate` representing the incoming off-curve of the bPoin. - """ + """, ) def _get_base_bcpIn(self) -> PairType[IntFloatType]: @@ -357,9 +360,9 @@ def _set_bcpIn(self, value: PairCollectionType[IntFloatType]) -> None: x, y = absoluteBCPIn(self.anchor, value) segment = self._segment if segment.type == "move" and value != (0, 0): - raise FontPartsError(("Cannot set the bcpIn for the first " - "point in an open contour.") - ) + raise FontPartsError( + ("Cannot set the bcpIn for the first " "point in an open contour.") + ) offCurves = segment.offCurve if offCurves: @@ -388,7 +391,7 @@ def _set_bcpIn(self, value: PairCollectionType[IntFloatType]) -> None: :return: A :ref:`type-coordinate` representing the outgoing off-curve of the bPoin. - """ + """, ) def _get_base_bcpOut(self) -> PairType[IntFloatType]: @@ -445,9 +448,9 @@ def _set_bcpOut(self, value: PairCollectionType[IntFloatType]) -> None: segment = self._segment nextSegment = self._nextSegment if nextSegment.type == "move" and value != (0, 0): - raise FontPartsError(("Cannot set the bcpOut for the last " - "point in an open contour.") - ) + raise FontPartsError( + ("Cannot set the bcpOut for the last " "point in an open contour.") + ) else: offCurves = nextSegment.offCurve if offCurves: @@ -483,7 +486,7 @@ def _set_bcpOut(self, value: PairCollectionType[IntFloatType]) -> None: :return: A :class:`str` representing the type of the bPoint. - """ + """, ) def _get_base_type(self) -> str: @@ -527,8 +530,7 @@ def _get_type(self) -> str: bType = "corner" if bType is None: - raise FontPartsError("A %s point can not be converted to a bPoint." - % typ) + raise FontPartsError("A %s point can not be converted to a bPoint." % typ) return bType def _set_type(self, value: str) -> None: @@ -579,7 +581,7 @@ def _set_type(self, value: str) -> None: >>> bPoint.index 0 - """ + """, ) def _get_base_index(self) -> Optional[int]: @@ -613,9 +615,9 @@ def _get_index(self) -> Optional[int]: # Transformation # -------------- - def _transformBy(self, - matrix: SextupleCollectionType[IntFloatType], - **kwargs: Any) -> None: + def _transformBy( + self, matrix: SextupleCollectionType[IntFloatType], **kwargs: Any + ) -> None: r"""Transform the native bPoint. This is the environment implementation of :meth:`BaseBPoint.transformBy`. @@ -659,18 +661,25 @@ def round(self) -> None: """ x, y = self.anchor - self.anchor = (normalizers.normalizeVisualRounding(x), - normalizers.normalizeVisualRounding(y)) + self.anchor = ( + normalizers.normalizeVisualRounding(x), + normalizers.normalizeVisualRounding(y), + ) x, y = self.bcpIn - self.bcpIn = (normalizers.normalizeVisualRounding(x), - normalizers.normalizeVisualRounding(y)) + self.bcpIn = ( + normalizers.normalizeVisualRounding(x), + normalizers.normalizeVisualRounding(y), + ) x, y = self.bcpOut - self.bcpOut = (normalizers.normalizeVisualRounding(x), - normalizers.normalizeVisualRounding(y)) + self.bcpOut = ( + normalizers.normalizeVisualRounding(x), + normalizers.normalizeVisualRounding(y), + ) -def relativeBCPIn(anchor: PairCollectionType[IntFloatType], - BCPIn: PairCollectionType[IntFloatType]) -> PairType[IntFloatType]: +def relativeBCPIn( + anchor: PairCollectionType[IntFloatType], BCPIn: PairCollectionType[IntFloatType] +) -> PairType[IntFloatType]: """convert absolute incoming bcp value to a relative value. :param anchor: The anchor reference point from which to measure the relative @@ -683,8 +692,9 @@ def relativeBCPIn(anchor: PairCollectionType[IntFloatType], return (BCPIn[0] - anchor[0], BCPIn[1] - anchor[1]) -def absoluteBCPIn(anchor: PairCollectionType[IntFloatType], - BCPIn: PairCollectionType[IntFloatType]) -> PairType[IntFloatType]: +def absoluteBCPIn( + anchor: PairCollectionType[IntFloatType], BCPIn: PairCollectionType[IntFloatType] +) -> PairType[IntFloatType]: """convert relative incoming bcp value to an absolute value. :param anchor: The anchor reference point from which the relative BCP value @@ -697,8 +707,9 @@ def absoluteBCPIn(anchor: PairCollectionType[IntFloatType], return (BCPIn[0] + anchor[0], BCPIn[1] + anchor[1]) -def relativeBCPOut(anchor: PairCollectionType[IntFloatType], - BCPOut: PairCollectionType[IntFloatType]) -> PairType[IntFloatType]: +def relativeBCPOut( + anchor: PairCollectionType[IntFloatType], BCPOut: PairCollectionType[IntFloatType] +) -> PairType[IntFloatType]: """convert absolute outgoing bcp value to a relative value. :param anchor: The anchor reference point from which to measure the relative @@ -711,8 +722,9 @@ def relativeBCPOut(anchor: PairCollectionType[IntFloatType], return (BCPOut[0] - anchor[0], BCPOut[1] - anchor[1]) -def absoluteBCPOut(anchor: PairCollectionType[IntFloatType], - BCPOut: PairCollectionType[IntFloatType]) -> PairType[IntFloatType]: +def absoluteBCPOut( + anchor: PairCollectionType[IntFloatType], BCPOut: PairCollectionType[IntFloatType] +) -> PairType[IntFloatType]: """convert relative outgoing bcp value to an absolute value. :param anchor: The anchor reference point from which the relative BCP value diff --git a/Lib/fontParts/base/base.py b/Lib/fontParts/base/base.py index a0fbdd1a..46c49621 100644 --- a/Lib/fontParts/base/base.py +++ b/Lib/fontParts/base/base.py @@ -1,7 +1,16 @@ # pylint: disable=C0103, C0114 from __future__ import annotations from typing import ( - Any, Callable, Dict, List, NoReturn, Optional, Tuple, Type, TypeVar, Union + Any, + Callable, + Dict, + List, + NoReturn, + Optional, + Tuple, + Type, + TypeVar, + Union, ) from copy import deepcopy import math @@ -18,7 +27,7 @@ InterpolatableType, ) -BaseObjectType = TypeVar('BaseObjectType', bound='BaseObject') +BaseObjectType = TypeVar("BaseObjectType", bound="BaseObject") # ------- # Helpers @@ -131,9 +140,11 @@ def __set__(self, obj: Any, value: Any) -> None: raise FontPartsError("no setter for %r" % self.name) -def interpolate(minValue: InterpolatableType, - maxValue: InterpolatableType, - factor: TransformationType) -> InterpolatableType: +def interpolate( + minValue: InterpolatableType, + maxValue: InterpolatableType, + factor: TransformationType, +) -> InterpolatableType: """Interpolate between two number-like objects. This method performs linear interpolation, calculating a value that is @@ -161,6 +172,7 @@ def interpolate(minValue: InterpolatableType, f"Factor must be an int or minValue float, not {type(factor).__name__}." ) from exc + # ------------ # Base Objects # ------------ @@ -183,6 +195,7 @@ class BaseObject: :param \**kwargs: Any keyword arguments. """ + # -------------- # Initialization # -------------- @@ -338,8 +351,9 @@ def raiseNotImplementedError(self) -> NoReturn: """ raise NotImplementedError( - "The {className} subclass does not implement this method." - .format(className=self.__class__.__name__) + "The {className} subclass does not implement this method.".format( + className=self.__class__.__name__ + ) ) # --------------------- @@ -381,6 +395,7 @@ class BaseDict(BaseObject): :cvar valueNormalizer: An optional normalizer function for values. """ + keyNormalizer: Optional[Any] = None valueNormalizer: Optional[Any] = None @@ -456,8 +471,7 @@ def items(self) -> List[Tuple[Any, Any]]: items = self._items() if self.keyNormalizer is not None and self.valueNormalizer is not None: items = [ - (self.keyNormalizer.__func__(key), - self.valueNormalizer.__func__(value)) + (self.keyNormalizer.__func__(key), self.valueNormalizer.__func__(value)) for (key, value) in items ] return items @@ -805,9 +819,11 @@ class TransformationMixin: # Transformations # --------------- - def transformBy(self, - matrix: SextupleCollectionType[IntFloatType], - origin: Optional[PairCollectionType[IntFloatType]] = None) -> None: + def transformBy( + self, + matrix: SextupleCollectionType[IntFloatType], + origin: Optional[PairCollectionType[IntFloatType]] = None, + ) -> None: """Transform the object according to the given matrix. :param matrix: The :ref:`type-transformation` to apply. @@ -834,9 +850,9 @@ def transformBy(self, matrix = tuple(t) self._transformBy(matrix) - def _transformBy(self, - matrix: SextupleCollectionType[IntFloatType], - **kwargs: Any) -> None: + def _transformBy( + self, matrix: SextupleCollectionType[IntFloatType], **kwargs: Any + ) -> None: r"""Transform the native object according to the given matrix. This is the environment implementation of :meth:`TransformationMixin.transformBy`. @@ -888,9 +904,11 @@ def _moveBy(self, value: PairCollectionType[IntFloatType], **kwargs: Any) -> Non t = transform.Offset(x, y) self.transformBy(tuple(t), **kwargs) - def scaleBy(self, - value: TransformationType, - origin: Optional[PairCollectionType[IntFloatType]] = None) -> None: + def scaleBy( + self, + value: TransformationType, + origin: Optional[PairCollectionType[IntFloatType]] = None, + ) -> None: """Scale the object according to the given values. :param value: The value to scale the glyph by as a single :class:`int` @@ -913,10 +931,12 @@ def scaleBy(self, origin = normalizers.normalizeCoordinateTuple(origin) self._scaleBy(value, origin=origin) - def _scaleBy(self, - value: TransformationType, - origin: Optional[PairCollectionType[IntFloatType]], - **kwargs: Any) -> None: + def _scaleBy( + self, + value: TransformationType, + origin: Optional[PairCollectionType[IntFloatType]], + **kwargs: Any, + ) -> None: r"""Scale the native object according to the given values. This is the environment implementation of :meth:`BaseObject.scaleBy`. @@ -940,9 +960,11 @@ def _scaleBy(self, t = transform.Identity.scale(x=x, y=y) self.transformBy(tuple(t), origin=origin, **kwargs) - def rotateBy(self, - value: IntFloatType, - origin: Optional[PairCollectionType[IntFloatType]] = None) -> None: + def rotateBy( + self, + value: IntFloatType, + origin: Optional[PairCollectionType[IntFloatType]] = None, + ) -> None: """Rotate the object by the specified value. :param value: The angle at which to rotate the object as an :class:`int` @@ -963,10 +985,12 @@ def rotateBy(self, origin = normalizers.normalizeCoordinateTuple(origin) self._rotateBy(value, origin=origin) - def _rotateBy(self, - value: IntFloatType, - origin: Optional[PairCollectionType[IntFloatType]], - **kwargs: Any) -> None: + def _rotateBy( + self, + value: IntFloatType, + origin: Optional[PairCollectionType[IntFloatType]], + **kwargs: Any, + ) -> None: r"""Rotate the native object by the specified value. This is the environment implementation of :meth:`TransformationMixin.rotateBy`. @@ -988,9 +1012,11 @@ def _rotateBy(self, t = transform.Identity.rotate(a) self.transformBy(tuple(t), origin=origin, **kwargs) - def skewBy(self, - value: TransformationType, - origin: Optional[PairCollectionType[IntFloatType]] = None) -> None: + def skewBy( + self, + value: TransformationType, + origin: Optional[PairCollectionType[IntFloatType]] = None, + ) -> None: """Skew the object by the given value. :param value: The value by which to skew the object as either a @@ -1013,10 +1039,12 @@ def skewBy(self, origin = normalizers.normalizeCoordinateTuple(origin) self._skewBy(value, origin=origin) - def _skewBy(self, - value: TransformationType, - origin: Optional[PairCollectionType[IntFloatType]], - **kwargs: Any) -> None: + def _skewBy( + self, + value: TransformationType, + origin: Optional[PairCollectionType[IntFloatType]], + **kwargs: Any, + ) -> None: r"""Skew the native object by the given value. This is the environment implementation of :meth:`TransformationMixin.skewBy`. @@ -1073,7 +1101,8 @@ def isCompatible(self, other: Any, cls: Type[Any]) -> Tuple[bool, Any]: raise TypeError( """Compatibility between an instance of %r and an \ instance of %r can not be checked.""" - % (cls.__name__, other.__class__.__name__)) + % (cls.__name__, other.__class__.__name__) + ) reporter = self.compatibilityReporterClass(self, other) self._isCompatible(other, reporter) return not reporter.fatal, reporter @@ -1118,7 +1147,7 @@ class SelectionMixin: False >>> obj.selected = True - """ + """, ) def _get_base_selected(self) -> bool: @@ -1170,15 +1199,14 @@ def _set_selected(self, value: bool) -> None: # Sub-Objects # ----------- @classmethod - def _getSelectedSubObjects(cls, - subObjects: CollectionType[Any]) -> Tuple[Any]: + def _getSelectedSubObjects(cls, subObjects: CollectionType[Any]) -> Tuple[Any]: selected = tuple(obj for obj in subObjects if obj.selected) return selected @classmethod - def _setSelectedSubObjects(cls, - subObjects: CollectionType[Any], - selected: CollectionType[Any]) -> None: + def _setSelectedSubObjects( + cls, subObjects: CollectionType[Any], selected: CollectionType[Any] + ) -> None: for obj in subObjects: obj.selected = obj in selected @@ -1199,7 +1227,7 @@ class PointPositionMixin: :return: The current point position as a :ref:`type-coordinate`. - """ + """, ) def _get_base_position(self) -> PairType[IntFloatType]: @@ -1270,7 +1298,7 @@ class IdentifierMixin: >>> object.identifier 'ILHGJlygfds' - """ + """, ) def _get_base_identifier(self) -> Optional[str]: @@ -1352,8 +1380,10 @@ def reference(obj: Callable[[], Any]) -> Callable[[], Any]: so this function was put in place to make sure existing code continued to function. The need for it is questionable, so it may be deleted soon. """ + def wrapper() -> Any: return obj + return wrapper diff --git a/Lib/fontParts/base/color.py b/Lib/fontParts/base/color.py index 8565a1e4..e83fe409 100644 --- a/Lib/fontParts/base/color.py +++ b/Lib/fontParts/base/color.py @@ -1,5 +1,4 @@ class Color(tuple): - """ An color object. This follows the :ref:`type-color`. """ @@ -7,23 +6,19 @@ class Color(tuple): def _get_r(self): return self[0] - r = property(_get_r, - "The color's red component as :ref:`type-int-float`.") + r = property(_get_r, "The color's red component as :ref:`type-int-float`.") def _get_g(self): return self[1] - g = property(_get_g, - "The color's green component as :ref:`type-int-float`.") + g = property(_get_g, "The color's green component as :ref:`type-int-float`.") def _get_b(self): return self[2] - b = property(_get_b, - "The color's blue component as :ref:`type-int-float`.") + b = property(_get_b, "The color's blue component as :ref:`type-int-float`.") def _get_a(self): return self[3] - a = property(_get_a, - "The color's alpha component as :ref:`type-int-float`.") + a = property(_get_a, "The color's alpha component as :ref:`type-int-float`.") diff --git a/Lib/fontParts/base/compatibility.py b/Lib/fontParts/base/compatibility.py index 9880a06c..c28e0986 100644 --- a/Lib/fontParts/base/compatibility.py +++ b/Lib/fontParts/base/compatibility.py @@ -6,7 +6,6 @@ class BaseCompatibilityReporter(object): - objectName = "Base" def __init__(self, obj1, obj2): @@ -20,8 +19,7 @@ def __init__(self, obj1, obj2): def _get_title(self): title = "{object1Name} + {object2Name}".format( - object1Name=self.object1Name, - object2Name=self.object2Name + object1Name=self.object1Name, object2Name=self.object2Name ) if self.fatal: return self.formatFatalString(title) @@ -55,9 +53,9 @@ def _get_object2Name(self): @staticmethod def _getObjectName(obj): if hasattr(obj, "name") and obj.name is not None: - return "\"%s\"" % obj.name + return '"%s"' % obj.name elif hasattr(obj, "identifier") and obj.identifier is not None: - return "\"%s\"" % obj.identifier + return '"%s"' % obj.identifier elif hasattr(obj, "index"): return "[%s]" % obj.index else: @@ -89,42 +87,47 @@ def reportSubObjects(reporters, showOK=True, showWarnings=True): return report @staticmethod - def reportCountDifference(subObjectName, - object1Name, object1Count, - object2Name, object2Count): - text = ("{object1Name} contains {object1Count} {subObjectName} | " - "{object2Name} contains {object2Count} {subObjectName}").format( + def reportCountDifference( + subObjectName, object1Name, object1Count, object2Name, object2Count + ): + text = ( + "{object1Name} contains {object1Count} {subObjectName} | " + "{object2Name} contains {object2Count} {subObjectName}" + ).format( subObjectName=subObjectName, object1Name=object1Name, object1Count=object1Count, object2Name=object2Name, - object2Count=object2Count + object2Count=object2Count, ) return text @staticmethod - def reportOrderDifference(subObjectName, - object1Name, object1Order, - object2Name, object2Order): - text = ("{object1Name} has {subObjectName} ordered {object1Order} | " - "{object2Name} has {object2Order}").format( + def reportOrderDifference( + subObjectName, object1Name, object1Order, object2Name, object2Order + ): + text = ( + "{object1Name} has {subObjectName} ordered {object1Order} | " + "{object2Name} has {object2Order}" + ).format( subObjectName=subObjectName, object1Name=object1Name, object1Order=object1Order, object2Name=object2Name, - object2Order=object2Order + object2Order=object2Order, ) return text @staticmethod - def reportDifferences(object1Name, subObjectName, - subObjectID, object2Name): - text = ("{object1Name} contains {subObjectName} {subObjectID} " - "not in {object2Name}").format( - object1Name=object1Name, - subObjectName=subObjectName, - subObjectID=subObjectID, - object2Name=object2Name, + def reportDifferences(object1Name, subObjectName, subObjectID, object2Name): + text = ( + "{object1Name} contains {subObjectName} {subObjectID} " + "not in {object2Name}" + ).format( + object1Name=object1Name, + subObjectName=subObjectName, + subObjectID=subObjectID, + object2Name=object2Name, ) return text @@ -133,8 +136,8 @@ def reportDifferences(object1Name, subObjectName, # Font # ---- -class FontCompatibilityReporter(BaseCompatibilityReporter): +class FontCompatibilityReporter(BaseCompatibilityReporter): objectName = "Font" def __init__(self, font1, font2): @@ -162,7 +165,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.font1Name, object1Count=len(font1.guidelines), object2Name=self.font2Name, - object2Count=len(font2.guidelines) + object2Count=len(font2.guidelines), ) report.append(self.formatWarningString(text)) for name in self.guidelinesMissingFromFont2: @@ -187,7 +190,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.font1Name, object1Count=len(font1.layerOrder), object2Name=self.font2Name, - object2Count=len(font2.layerOrder) + object2Count=len(font2.layerOrder), ) report.append(self.formatWarningString(text)) for name in self.layersMissingFromFont2: @@ -206,8 +209,9 @@ def report(self, showOK=True, showWarnings=True): object2Name=self.font1Name, ) report.append(self.formatWarningString(text)) - report += self.reportSubObjects(self.layers, showOK=showOK, - showWarnings=showWarnings) + report += self.reportSubObjects( + self.layers, showOK=showOK, showWarnings=showWarnings + ) if report or showOK: report.insert(0, self.title) @@ -218,8 +222,8 @@ def report(self, showOK=True, showWarnings=True): # Layer # ----- -class LayerCompatibilityReporter(BaseCompatibilityReporter): +class LayerCompatibilityReporter(BaseCompatibilityReporter): objectName = "Layer" def __init__(self, layer1, layer2): @@ -244,7 +248,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.layer1Name, object1Count=len(layer1), object2Name=self.layer2Name, - object2Count=len(layer2) + object2Count=len(layer2), ) report.append(self.formatWarningString(text)) for name in self.glyphsMissingFromLayer2: @@ -263,9 +267,9 @@ def report(self, showOK=True, showWarnings=True): object2Name=self.layer1Name, ) report.append(self.formatWarningString(text)) - report += self.reportSubObjects(self.glyphs, - showOK=showOK, - showWarnings=showWarnings) + report += self.reportSubObjects( + self.glyphs, showOK=showOK, showWarnings=showWarnings + ) if report or showOK: report.insert(0, self.title) @@ -276,8 +280,8 @@ def report(self, showOK=True, showWarnings=True): # Glyph # ----- -class GlyphCompatibilityReporter(BaseCompatibilityReporter): +class GlyphCompatibilityReporter(BaseCompatibilityReporter): objectName = "Glyph" def __init__(self, glyph1, glyph2): @@ -315,12 +319,12 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Count=len(glyph1), object2Name=self.glyph2Name, - object2Count=len(glyph2) + object2Count=len(glyph2), ) report.append(self.formatFatalString(text)) - report += self.reportSubObjects(self.contours, - showOK=showOK, - showWarnings=showWarnings) + report += self.reportSubObjects( + self.contours, showOK=showOK, showWarnings=showWarnings + ) # Component test if self.componentCountDifference: @@ -329,7 +333,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Count=len(glyph1.components), object2Name=self.glyph2Name, - object2Count=len(glyph2.components) + object2Count=len(glyph2.components), ) report.append(self.formatFatalString(text)) elif self.componentOrderDifference: @@ -338,7 +342,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Order=[c.baseGlyph for c in glyph1.components], object2Name=self.glyph2Name, - object2Order=[c.baseGlyph for c in glyph2.components] + object2Order=[c.baseGlyph for c in glyph2.components], ) report.append(self.formatWarningString(text)) for name in self.componentsMissingFromGlyph2: @@ -365,7 +369,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Count=len(glyph1.anchors), object2Name=self.glyph2Name, - object2Count=len(glyph2.anchors) + object2Count=len(glyph2.anchors), ) report.append(self.formatWarningString(text)) elif self.anchorOrderDifference: @@ -374,7 +378,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Order=[a.name for a in glyph1.anchors], object2Name=self.glyph2Name, - object2Order=[a.name for a in glyph2.anchors] + object2Order=[a.name for a in glyph2.anchors], ) report.append(self.formatWarningString(text)) for name in self.anchorsMissingFromGlyph2: @@ -401,7 +405,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.glyph1Name, object1Count=len(glyph1.guidelines), object2Name=self.glyph2Name, - object2Count=len(glyph2.guidelines) + object2Count=len(glyph2.guidelines), ) report.append(self.formatWarningString(text)) for name in self.guidelinesMissingFromGlyph2: @@ -430,8 +434,8 @@ def report(self, showOK=True, showWarnings=True): # Contour # ------- -class ContourCompatibilityReporter(BaseCompatibilityReporter): +class ContourCompatibilityReporter(BaseCompatibilityReporter): objectName = "Contour" def __init__(self, contour1, contour2): @@ -456,7 +460,7 @@ def report(self, showOK=True, showWarnings=True): object1Name=self.contour1Name, object1Count=len(contour1), object2Name=self.contour2Name, - object2Count=len(contour2) + object2Count=len(contour2), ) report.append(self.formatFatalString(text)) if self.openDifference: @@ -469,7 +473,7 @@ def report(self, showOK=True, showWarnings=True): contour1Name=self.contour1Name, state1=state1, contour2Name=self.contour2Name, - state2=state2 + state2=state2, ) report.append(self.formatFatalString(text)) if self.directionDifference: @@ -482,12 +486,12 @@ def report(self, showOK=True, showWarnings=True): contour1Name=self.contour1Name, state1=state1, contour2Name=self.contour2Name, - state2=state2 + state2=state2, ) report.append(self.formatFatalString(text)) - report += self.reportSubObjects(self.segments, - showOK=showOK, - showWarnings=showWarnings) + report += self.reportSubObjects( + self.segments, showOK=showOK, showWarnings=showWarnings + ) if report or showOK: report.insert(0, self.title) return "\n".join(report) @@ -497,8 +501,8 @@ def report(self, showOK=True, showWarnings=True): # Segment # ------- -class SegmentCompatibilityReporter(BaseCompatibilityReporter): +class SegmentCompatibilityReporter(BaseCompatibilityReporter): objectName = "Segment" def __init__(self, contour1, contour2): @@ -521,25 +525,24 @@ def report(self, showOK=True, showWarnings=True): segment1Name=self.segment1Name, type1=type1, segment2Name=self.segment2Name, - type2=type2 + type2=type2, ) report.append(self.formatFatalString(text)) if report or showOK: report.insert(0, self.title) return "\n".join(report) + # --------- # Component # --------- class ComponentCompatibilityReporter(BaseCompatibilityReporter): - objectName = "Component" def __init__(self, component1, component2): - super(ComponentCompatibilityReporter, self).__init__(component1, - component2) + super(ComponentCompatibilityReporter, self).__init__(component1, component2) self.baseDifference = False component1 = dynamicProperty("object1") @@ -554,25 +557,27 @@ def report(self, showOK=True, showWarnings=True): if self.baseDifference: name1 = component1.baseName name2 = component2.baseName - text = ("{component1Name} has base glyph {name1} | " - "{component2Name} has base glyph {name2}").format( + text = ( + "{component1Name} has base glyph {name1} | " + "{component2Name} has base glyph {name2}" + ).format( component1Name=self.component1Name, name1=name1, component2Name=self.component2Name, - name2=name2 + name2=name2, ) report.append(self.formatWarningString(text)) if report or showOK: report.insert(0, self.title) return "\n".join(report) + # ------ # Anchor # ------ class AnchorCompatibilityReporter(BaseCompatibilityReporter): - objectName = "Anchor" def __init__(self, anchor1, anchor2): @@ -591,12 +596,13 @@ def report(self, showOK=True, showWarnings=True): if self.nameDifference: name1 = anchor1.name name2 = anchor2.name - text = ("{anchor1Name} has name {name1} | " - "{anchor2Name} has name {name2}").format( + text = ( + "{anchor1Name} has name {name1} | " "{anchor2Name} has name {name2}" + ).format( anchor1Name=self.anchor1Name, name1=name1, anchor2Name=self.anchor2Name, - name2=name2 + name2=name2, ) report.append(self.formatWarningString(text)) if report or showOK: @@ -608,13 +614,12 @@ def report(self, showOK=True, showWarnings=True): # Guideline # --------- -class GuidelineCompatibilityReporter(BaseCompatibilityReporter): +class GuidelineCompatibilityReporter(BaseCompatibilityReporter): objectName = "Guideline" def __init__(self, guideline1, guideline2): - super(GuidelineCompatibilityReporter, self).__init__(guideline1, - guideline2) + super(GuidelineCompatibilityReporter, self).__init__(guideline1, guideline2) self.nameDifference = False guideline1 = dynamicProperty("object1") @@ -629,12 +634,14 @@ def report(self, showOK=True, showWarnings=True): if self.nameDifference: name1 = guideline1.name name2 = guideline2.name - text = ("{guideline1Name} has name {name1} | " - "{guideline2Name} has name {name2}").format( + text = ( + "{guideline1Name} has name {name1} | " + "{guideline2Name} has name {name2}" + ).format( guideline1Name=self.guideline1Name, name1=name1, guideline2Name=self.guideline2Name, - name2=name2 + name2=name2, ) report.append(self.formatWarningString(text)) if report or showOK: diff --git a/Lib/fontParts/base/component.py b/Lib/fontParts/base/component.py index 4f135833..a2a0e763 100644 --- a/Lib/fontParts/base/component.py +++ b/Lib/fontParts/base/component.py @@ -9,26 +9,22 @@ SelectionMixin, IdentifierMixin, dynamicProperty, - reference + reference, ) from fontParts.base.compatibility import ComponentCompatibilityReporter from fontParts.base.deprecated import DeprecatedComponent, RemovedComponent class BaseComponent( - BaseObject, - TransformationMixin, - InterpolationMixin, - SelectionMixin, - IdentifierMixin, - DeprecatedComponent, - RemovedComponent - ): - - copyAttributes = ( - "baseGlyph", - "transformation" - ) + BaseObject, + TransformationMixin, + InterpolationMixin, + SelectionMixin, + IdentifierMixin, + DeprecatedComponent, + RemovedComponent, +): + copyAttributes = ("baseGlyph", "transformation") def _reprContents(self): contents = [ @@ -86,8 +82,9 @@ def _get_font(self): # baseGlyph - baseGlyph = dynamicProperty("base_baseGlyph", - "The name of the glyph the component references.") + baseGlyph = dynamicProperty( + "base_baseGlyph", "The name of the glyph the component references." + ) def _get_base_baseGlyph(self): value = self._get_baseGlyph() @@ -117,8 +114,9 @@ def _set_baseGlyph(self, value): # transformation - transformation = dynamicProperty("base_transformation", - "The component's transformation matrix.") + transformation = dynamicProperty( + "base_transformation", "The component's transformation matrix." + ) def _get_base_transformation(self): value = self._get_transformation() @@ -203,9 +201,13 @@ def _set_scale(self, value): # index - index = dynamicProperty("base_index", - ("The index of the component within the " - "ordered list of the parent glyph's components.")) + index = dynamicProperty( + "base_index", + ( + "The index of the component within the " + "ordered list of the parent glyph's components." + ), + ) def _get_base_index(self): glyph = self.glyph @@ -255,6 +257,7 @@ def _draw(self, pen, **kwargs): Subclasses may override this method. """ from fontTools.ufoLib.pointPen import PointToSegmentPen + adapter = PointToSegmentPen(pen) self.drawPoints(adapter) @@ -273,8 +276,12 @@ def _drawPoints(self, pen, **kwargs): # point pens that have not been upgraded # to point pen protocol 2. try: - pen.addComponent(self.baseGlyph, self.transformation, - identifier=self.identifier, **kwargs) + pen.addComponent( + self.baseGlyph, + self.transformation, + identifier=self.identifier, + **kwargs, + ) except TypeError: pen.addComponent(self.baseGlyph, self.transformation, **kwargs) @@ -379,13 +386,15 @@ def _pointInside(self, point): Subclasses may override this method. """ from fontTools.pens.pointInsidePen import PointInsidePen + pen = PointInsidePen(glyphSet=self.layer, testPoint=point, evenOdd=False) self.draw(pen) return pen.getResult() - bounds = dynamicProperty("base_bounds", - ("The bounds of the component: " - "(xMin, yMin, xMax, yMax) or None.")) + bounds = dynamicProperty( + "base_bounds", + ("The bounds of the component: " "(xMin, yMin, xMax, yMax) or None."), + ) def _get_base_bounds(self): value = self._get_bounds() @@ -398,6 +407,7 @@ def _get_bounds(self): Subclasses may override this method. """ from fontTools.pens.boundsPen import BoundsPen + pen = BoundsPen(self.layer) self.draw(pen) return pen.bounds diff --git a/Lib/fontParts/base/contour.py b/Lib/fontParts/base/contour.py index 9efc8da6..77f424ee 100644 --- a/Lib/fontParts/base/contour.py +++ b/Lib/fontParts/base/contour.py @@ -6,7 +6,7 @@ SelectionMixin, IdentifierMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.compatibility import ContourCompatibilityReporter @@ -15,15 +15,14 @@ class BaseContour( - BaseObject, - TransformationMixin, - InterpolationMixin, - SelectionMixin, - IdentifierMixin, - DeprecatedContour, - RemovedContour - ): - + BaseObject, + TransformationMixin, + InterpolationMixin, + SelectionMixin, + IdentifierMixin, + DeprecatedContour, + RemovedContour, +): segmentClass = None bPointClass = None @@ -51,8 +50,7 @@ def copyData(self, source): _glyph = None - glyph = dynamicProperty("glyph", - "The contour's parent :class:`BaseGlyph`.") + glyph = dynamicProperty("glyph", "The contour's parent :class:`BaseGlyph`.") def _get_glyph(self): if self._glyph is None: @@ -100,7 +98,7 @@ def _get_layer(self): >>> contour.index = 0 The value will always be a :ref:`type-int`. - """ + """, ) def _get_base_index(self): @@ -176,6 +174,7 @@ def _draw(self, pen, **kwargs): Subclasses may override this method. """ from fontTools.ufoLib.pointPen import PointToSegmentPen + adapter = PointToSegmentPen(pen) self.drawPoints(adapter) @@ -204,12 +203,20 @@ def _drawPoints(self, pen, **kwargs): if typ == "offcurve": typ = None try: - pen.addPoint(pt=(point.x, point.y), segmentType=typ, - smooth=point.smooth, name=point.name, - identifier=point.identifier) + pen.addPoint( + pt=(point.x, point.y), + segmentType=typ, + smooth=point.smooth, + name=point.name, + identifier=point.identifier, + ) except TypeError: - pen.addPoint(pt=(point.x, point.y), segmentType=typ, - smooth=point.smooth, name=point.name) + pen.addPoint( + pt=(point.x, point.y), + segmentType=typ, + smooth=point.smooth, + name=point.name, + ) pen.endPath() # ------------------ @@ -316,8 +323,7 @@ def _isCompatible(self, other, reporter): # Open # ---- - open = dynamicProperty("base_open", - "Boolean indicating if the contour is open.") + open = dynamicProperty("base_open", "Boolean indicating if the contour is open.") def _get_base_open(self): value = self._get_open() @@ -334,9 +340,10 @@ def _get_open(self): # Direction # --------- - clockwise = dynamicProperty("base_clockwise", - ("Boolean indicating if the contour's " - "winding direction is clockwise.")) + clockwise = dynamicProperty( + "base_clockwise", + ("Boolean indicating if the contour's " "winding direction is clockwise."), + ) def _get_base_clockwise(self): value = self._get_clockwise() @@ -393,6 +400,7 @@ def _pointInside(self, point): Subclasses may override this method. """ from fontTools.pens.pointInsidePen import PointInsidePen + pen = PointInsidePen(glyphSet=None, testPoint=point, evenOdd=False) self.draw(pen) return pen.getResult() @@ -419,9 +427,9 @@ def _contourInside(self, otherContour): # Bounds and Area # --------------- - bounds = dynamicProperty("bounds", - ("The bounds of the contour: " - "(xMin, yMin, xMax, yMax) or None.")) + bounds = dynamicProperty( + "bounds", ("The bounds of the contour: " "(xMin, yMin, xMax, yMax) or None.") + ) def _get_base_bounds(self): value = self._get_bounds() @@ -434,13 +442,14 @@ def _get_bounds(self): Subclasses may override this method. """ from fontTools.pens.boundsPen import BoundsPen + pen = BoundsPen(self.layer) self.draw(pen) return pen.bounds - area = dynamicProperty("area", - ("The area of the contour: " - "A positive number or None.")) + area = dynamicProperty( + "area", ("The area of the contour: " "A positive number or None.") + ) def _get_base_area(self): value = self._get_area() @@ -453,6 +462,7 @@ def _get_area(self): Subclasses may override this method. """ from fontTools.pens.areaPen import AreaPen + pen = AreaPen(self.layer) self.draw(pen) return abs(pen.value) @@ -556,8 +566,9 @@ def _appendSegment(self, type=None, points=None, smooth=False, **kwargs): """ Subclasses may override this method. """ - self._insertSegment(len(self), type=type, points=points, - smooth=smooth, **kwargs) + self._insertSegment( + len(self), type=type, points=points, smooth=smooth, **kwargs + ) def insertSegment(self, index, type=None, points=None, smooth=False, segment=None): """ @@ -577,11 +588,11 @@ def insertSegment(self, index, type=None, points=None, smooth=False, segment=Non pts.append(pt) points = pts smooth = normalizers.normalizeBoolean(smooth) - self._insertSegment(index=index, type=type, - points=points, smooth=smooth) + self._insertSegment(index=index, type=type, points=points, smooth=smooth) - def _insertSegment(self, index=None, type=None, points=None, - smooth=False, **kwargs): + def _insertSegment( + self, index=None, type=None, points=None, smooth=False, **kwargs + ): """ Subclasses may override this method. """ @@ -640,7 +651,9 @@ def setStartSegment(self, segment): if segmentIndex == 0: return if segmentIndex >= len(segments): - raise ValueError(("The contour does not contain a segment at index %d" % segmentIndex)) + raise ValueError( + ("The contour does not contain a segment at index %d" % segmentIndex) + ) self._setStartSegment(segmentIndex) def _setStartSegment(self, segmentIndex, **kwargs): @@ -673,7 +686,9 @@ def _get_bPoints(self): bPoints.append(bPoint) return tuple(bPoints) - def appendBPoint(self, type=None, anchor=None, bcpIn=None, bcpOut=None, bPoint=None): + def appendBPoint( + self, type=None, anchor=None, bcpIn=None, bcpOut=None, bPoint=None + ): """ Append a bPoint to the contour. """ @@ -700,15 +715,11 @@ def _appendBPoint(self, type, anchor, bcpIn=None, bcpOut=None, **kwargs): """ Subclasses may override this method. """ - self.insertBPoint( - len(self.bPoints), - type, - anchor, - bcpIn=bcpIn, - bcpOut=bcpOut - ) + self.insertBPoint(len(self.bPoints), type, anchor, bcpIn=bcpIn, bcpOut=bcpOut) - def insertBPoint(self, index, type=None, anchor=None, bcpIn=None, bcpOut=None, bPoint=None): + def insertBPoint( + self, index, type=None, anchor=None, bcpIn=None, bcpOut=None, bPoint=None + ): """ Insert a bPoint at index in the contour. """ @@ -730,8 +741,9 @@ def insertBPoint(self, index, type=None, anchor=None, bcpIn=None, bcpOut=None, b if bcpOut is None: bcpOut = (0, 0) bcpOut = normalizers.normalizeCoordinateTuple(bcpOut) - self._insertBPoint(index=index, type=type, anchor=anchor, - bcpIn=bcpIn, bcpOut=bcpOut) + self._insertBPoint( + index=index, type=type, anchor=anchor, bcpIn=bcpIn, bcpOut=bcpOut + ) def _insertBPoint(self, index, type, anchor, bcpIn, bcpOut, **kwargs): """ @@ -740,8 +752,7 @@ def _insertBPoint(self, index, type, anchor, bcpIn, bcpOut, **kwargs): # insert a simple line segment at the given anchor # look it up as a bPoint and change the bcpIn and bcpOut there # this avoids code duplication - self._insertSegment(index=index, type="line", - points=[anchor], smooth=False) + self._insertSegment(index=index, type="line", points=[anchor], smooth=False) bPoints = self.bPoints index += 1 if index >= len(bPoints): @@ -801,8 +812,7 @@ def _get_points(self): """ Subclasses may override this method. """ - return tuple(self._getitem__points(i) - for i in range(self._len__points())) + return tuple(self._getitem__points(i) for i in range(self._len__points())) def _len__points(self): return self._lenPoints() @@ -840,7 +850,15 @@ def _getPointIndex(self, point): return i raise FontPartsError("The point could not be found.") - def appendPoint(self, position=None, type="line", smooth=False, name=None, identifier=None, point=None): + def appendPoint( + self, + position=None, + type="line", + smooth=False, + name=None, + identifier=None, + point=None, + ): """ Append a point to the contour. """ @@ -859,10 +877,19 @@ def appendPoint(self, position=None, type="line", smooth=False, name=None, ident type=type, smooth=smooth, name=name, - identifier=identifier + identifier=identifier, ) - def insertPoint(self, index, position=None, type="line", smooth=False, name=None, identifier=None, point=None): + def insertPoint( + self, + index, + position=None, + type="line", + smooth=False, + name=None, + identifier=None, + point=None, + ): """ Insert a point into the contour. """ @@ -889,11 +916,19 @@ def insertPoint(self, index, position=None, type="line", smooth=False, name=None type=type, smooth=smooth, name=name, - identifier=identifier + identifier=identifier, ) - def _insertPoint(self, index, position, type="line", - smooth=False, name=None, identifier=None, **kwargs): + def _insertPoint( + self, + index, + position, + type="line", + smooth=False, + name=None, + identifier=None, + **kwargs, + ): """ position will be a valid position (x, y). type will be a valid type. @@ -945,7 +980,9 @@ def setStartPoint(self, point): if pointIndex == 0: return if pointIndex >= len(points): - raise ValueError(("The contour does not contain a point at index %d" % pointIndex)) + raise ValueError( + ("The contour does not contain a point at index %d" % pointIndex) + ) self._setStartPoint(pointIndex) def _setStartPoint(self, pointIndex, **kwargs): @@ -964,7 +1001,7 @@ def _setStartPoint(self, pointIndex, **kwargs): type=point.type, smooth=point.smooth, name=point.name, - identifier=point.identifier + identifier=point.identifier, ) # --------- @@ -990,12 +1027,14 @@ def _setStartPoint(self, pointIndex, **kwargs): Setting also supports segment indexes: >>> contour.selectedSegments = [0, 2] - """ + """, ) def _get_base_selectedSegments(self): - selected = tuple(normalizers.normalizeSegment(segment) - for segment in self._get_selectedSegments()) + selected = tuple( + normalizers.normalizeSegment(segment) + for segment in self._get_selectedSegments() + ) return selected def _get_selectedSegments(self): @@ -1039,12 +1078,13 @@ def _set_selectedSegments(self, value): Setting also supports point indexes: >>> contour.selectedPoints = [0, 2] - """ + """, ) def _get_base_selectedPoints(self): - selected = tuple(normalizers.normalizePoint(point) - for point in self._get_selectedPoints()) + selected = tuple( + normalizers.normalizePoint(point) for point in self._get_selectedPoints() + ) return selected def _get_selectedPoints(self): @@ -1088,12 +1128,14 @@ def _set_selectedPoints(self, value): Setting also supports bPoint indexes: >>> contour.selectedBPoints = [0, 2] - """ + """, ) def _get_base_selectedBPoints(self): - selected = tuple(normalizers.normalizeBPoint(bPoint) - for bPoint in self._get_selectedBPoints()) + selected = tuple( + normalizers.normalizeBPoint(bPoint) + for bPoint in self._get_selectedBPoints() + ) return selected def _get_selectedBPoints(self): diff --git a/Lib/fontParts/base/deprecated.py b/Lib/fontParts/base/deprecated.py index 5159a331..d6e62b41 100644 --- a/Lib/fontParts/base/deprecated.py +++ b/Lib/fontParts/base/deprecated.py @@ -12,25 +12,26 @@ class RemovedError(Exception): # = base = # ======== -class RemovedBase(object): +class RemovedBase(object): def setParent(self, parent): objName = self.__class__.__name__.replace("Removed", "") raise RemovedError("'%s.setParent()'" % objName) class DeprecatedBase(object): - def update(self): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.update': use %s.changed()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.update': use %s.changed()" % (objName, objName), DeprecationWarning + ) self.changed() def setChanged(self): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.setChanged': use %s.changed()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.setChanged': use %s.changed()" % (objName, objName), DeprecationWarning + ) self.changed() @@ -38,24 +39,27 @@ def setChanged(self): # = transformation = # ================== -class DeprecatedTransformation(object): +class DeprecatedTransformation(object): def move(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.move()': use %s.moveBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.move()': use %s.moveBy()" % (objName, objName), DeprecationWarning + ) self.moveBy(*args, **kwargs) def translate(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.translate()': use %s.moveBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.translate()': use %s.moveBy()" % (objName, objName), DeprecationWarning + ) self.moveBy(*args, **kwargs) def scale(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.scale()': use %s.scaleBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.scale()': use %s.scaleBy()" % (objName, objName), DeprecationWarning + ) if "center" in kwargs: kwargs["origin"] = kwargs["center"] del kwargs["center"] @@ -63,8 +67,9 @@ def scale(self, *args, **kwargs): def rotate(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.rotate()': use %s.rotateBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.rotate()': use %s.rotateBy()" % (objName, objName), DeprecationWarning + ) if "offset" in kwargs: kwargs["origin"] = kwargs["offset"] del kwargs["offset"] @@ -72,14 +77,17 @@ def rotate(self, *args, **kwargs): def transform(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.transform()': use %s.transformBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.transform()': use %s.transformBy()" % (objName, objName), + DeprecationWarning, + ) self.transformBy(*args, **kwargs) def skew(self, *args, **kwargs): objName = self.__class__.__name__.replace("Deprecated", "") - warnings.warn("'%s.skew()': use %s.skewBy()" - % (objName, objName), DeprecationWarning) + warnings.warn( + "'%s.skew()': use %s.skewBy()" % (objName, objName), DeprecationWarning + ) if "offset" in kwargs: kwargs["origin"] = kwargs["offset"] del kwargs["offset"] @@ -90,28 +98,30 @@ def skew(self, *args, **kwargs): # = Point = # ========= -class RemovedPoint(RemovedBase): +class RemovedPoint(RemovedBase): @staticmethod def select(state=True): raise RemovedError("'Point.select'") class DeprecatedPoint(DeprecatedBase, DeprecatedTransformation): - def _generateIdentifier(self): - warnings.warn("'Point._generateIdentifier()': use 'Point._getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Point._generateIdentifier()': use 'Point._getIdentifier()'", + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn("'Point.generateIdentifier()': use 'Point.getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Point.generateIdentifier()': use 'Point.getIdentifier()'", + DeprecationWarning, + ) return self.getIdentifier() def getParent(self): - warnings.warn("'Point.getParent()': use 'Point.contour'", - DeprecationWarning) + warnings.warn("'Point.getParent()': use 'Point.contour'", DeprecationWarning) return self.contour @@ -119,28 +129,30 @@ def getParent(self): # = BPoint = # ========== -class RemovedBPoint(RemovedBase): +class RemovedBPoint(RemovedBase): @staticmethod def select(state=True): raise RemovedError("'BPoint.select'") class DeprecatedBPoint(DeprecatedBase, DeprecatedTransformation): - def _generateIdentifier(self): - warnings.warn("'BPoint._generateIdentifier()': use 'BPoint._getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'BPoint._generateIdentifier()': use 'BPoint._getIdentifier()'", + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn("'BPoint.generateIdentifier()': use 'BPoint.getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'BPoint.generateIdentifier()': use 'BPoint.getIdentifier()'", + DeprecationWarning, + ) return self.getIdentifier() def getParent(self): - warnings.warn("'BPoint.getParent()': use 'BPoint.contour'", - DeprecationWarning) + warnings.warn("'BPoint.getParent()': use 'BPoint.contour'", DeprecationWarning) return self.contour @@ -148,33 +160,36 @@ def getParent(self): # = Anchor = # ========== -class RemovedAnchor(RemovedBase): +class RemovedAnchor(RemovedBase): @staticmethod def draw(pen): raise RemovedError("'Anchor.draw': UFO3 is not drawing anchors into pens") @staticmethod def drawPoints(pen): - raise RemovedError(("'Anchor.drawPoints': UFO3 is not drawing " - "anchors into point pens")) + raise RemovedError( + ("'Anchor.drawPoints': UFO3 is not drawing " "anchors into point pens") + ) class DeprecatedAnchor(DeprecatedBase, DeprecatedTransformation): - def _generateIdentifier(self): - warnings.warn("'Anchor._generateIdentifier()': use 'Anchor._getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Anchor._generateIdentifier()': use 'Anchor._getIdentifier()'", + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn("'Anchor.generateIdentifier()': use 'Anchor.getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Anchor.generateIdentifier()': use 'Anchor.getIdentifier()'", + DeprecationWarning, + ) return self.getIdentifier() def getParent(self): - warnings.warn("'Anchor.getParent()': use 'Anchor.glyph'", - DeprecationWarning) + warnings.warn("'Anchor.getParent()': use 'Anchor.glyph'", DeprecationWarning) return self.glyph @@ -182,63 +197,65 @@ def getParent(self): # = Component = # ============= -class RemovedComponent(RemovedBase): +class RemovedComponent(RemovedBase): pass class DeprecatedComponent(DeprecatedBase): - def _get_box(self): - warnings.warn("'Component.box': use Component.bounds", - DeprecationWarning) + warnings.warn("'Component.box': use Component.bounds", DeprecationWarning) return self.bounds box = property(_get_box, doc="Deprecated Component.box") def _generateIdentifier(self): - warnings.warn(("'Component._generateIdentifier()': use " - "'Component._getIdentifier()'"), - DeprecationWarning) + warnings.warn( + ("'Component._generateIdentifier()': use " "'Component._getIdentifier()'"), + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn(("'Component.generateIdentifier()': " - "use 'Component.getIdentifier()'"), - DeprecationWarning) + warnings.warn( + ("'Component.generateIdentifier()': " "use 'Component.getIdentifier()'"), + DeprecationWarning, + ) return self.getIdentifier() def getParent(self): - warnings.warn("'Component.getParent()': use 'Component.glyph'", - DeprecationWarning) + warnings.warn( + "'Component.getParent()': use 'Component.glyph'", DeprecationWarning + ) return self.glyph def move(self, *args, **kwargs): - warnings.warn("'Component.move()': use Component.moveBy()", - DeprecationWarning) + warnings.warn("'Component.move()': use Component.moveBy()", DeprecationWarning) self.moveBy(*args, **kwargs) def translate(self, *args, **kwargs): - warnings.warn("'Component.translate()': use Component.moveBy()", - DeprecationWarning) + warnings.warn( + "'Component.translate()': use Component.moveBy()", DeprecationWarning + ) self.moveBy(*args, **kwargs) def rotate(self, *args, **kwargs): - warnings.warn("'Component.rotate()': use Component.rotateBy()", - DeprecationWarning) + warnings.warn( + "'Component.rotate()': use Component.rotateBy()", DeprecationWarning + ) if "offset" in kwargs: kwargs["origin"] = kwargs["offset"] del kwargs["offset"] self.rotateBy(*args, **kwargs) def transform(self, *args, **kwargs): - warnings.warn("'Component.transform()': use Component.transformBy()", - DeprecationWarning) + warnings.warn( + "'Component.transform()': use Component.transformBy()", DeprecationWarning + ) self.transformBy(*args, **kwargs) def skew(self, *args, **kwargs): - warnings.warn("'Component.skew()': use Component.skewBy()", - DeprecationWarning) + warnings.warn("'Component.skew()': use Component.skewBy()", DeprecationWarning) if "offset" in kwargs: kwargs["origin"] = kwargs["offset"] del kwargs["offset"] @@ -249,8 +266,8 @@ def skew(self, *args, **kwargs): # = Segment = # =========== -class RemovedSegment(RemovedBase): +class RemovedSegment(RemovedBase): @staticmethod def insertPoint(point): raise RemovedError("Segment.insertPoint()") @@ -261,10 +278,10 @@ def removePoint(point): class DeprecatedSegment(DeprecatedBase, DeprecatedTransformation): - def getParent(self): - warnings.warn("'Segment.getParent()': use 'Segment.contour'", - DeprecationWarning) + warnings.warn( + "'Segment.getParent()': use 'Segment.contour'", DeprecationWarning + ) return self.contour @@ -272,13 +289,12 @@ def getParent(self): # = Contour = # =========== -class RemovedContour(RemovedBase): +class RemovedContour(RemovedBase): pass class DeprecatedContour(DeprecatedBase, DeprecatedTransformation): - def _get_box(self): warnings.warn("'Contour.box': use Contour.bounds", DeprecationWarning) return self.bounds @@ -286,28 +302,43 @@ def _get_box(self): box = property(_get_box, doc="Deprecated Contour.box") def reverseContour(self): - warnings.warn("'Contour.reverseContour()': use 'Contour.reverse()'", - DeprecationWarning) + warnings.warn( + "'Contour.reverseContour()': use 'Contour.reverse()'", DeprecationWarning + ) self.reverse() def _generateIdentifier(self): - warnings.warn("'Contour._generateIdentifier()': use 'Contour._getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Contour._generateIdentifier()': use 'Contour._getIdentifier()'", + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn("'Contour.generateIdentifier()': use 'Contour.getIdentifier()'", - DeprecationWarning) + warnings.warn( + "'Contour.generateIdentifier()': use 'Contour.getIdentifier()'", + DeprecationWarning, + ) return self.getIdentifier() def _generateIdentifierforPoint(self, point): - warnings.warn(("'Contour._generateIdentifierforPoint()': use " - "'Contour._getIdentifierforPoint()'"), DeprecationWarning) + warnings.warn( + ( + "'Contour._generateIdentifierforPoint()': use " + "'Contour._getIdentifierforPoint()'" + ), + DeprecationWarning, + ) return self._getIdentifierforPoint(point) def generateIdentifierforPoint(self, point): - warnings.warn(("'Contour.generateIdentifierforPoint()': use " - "'Contour.getIdentifierForPoint()'"), DeprecationWarning) + warnings.warn( + ( + "'Contour.generateIdentifierforPoint()': use " + "'Contour.getIdentifierForPoint()'" + ), + DeprecationWarning, + ) return self.getIdentifierForPoint(point) def getParent(self): @@ -319,8 +350,8 @@ def getParent(self): # = Glyph = # ========= -class RemovedGlyph(RemovedBase): +class RemovedGlyph(RemovedBase): @staticmethod def center(padding=None): raise RemovedError("'Glyph.center()'") @@ -335,7 +366,6 @@ def clearHGuides(): class DeprecatedGlyph(DeprecatedBase, DeprecatedTransformation): - def _get_mark(self): warnings.warn("'Glyph.mark': use Glyph.markColor", DeprecationWarning) return self.markColor @@ -353,30 +383,31 @@ def _get_box(self): box = property(_get_box, doc="Deprecated Glyph.box") def getAnchors(self): - warnings.warn("'Glyph.getAnchors()': use Glyph.anchors", - DeprecationWarning) + warnings.warn("'Glyph.getAnchors()': use Glyph.anchors", DeprecationWarning) return self.anchors def getComponents(self): - warnings.warn("'Glyph.getComponents()': use Glyph.components", - DeprecationWarning) + warnings.warn( + "'Glyph.getComponents()': use Glyph.components", DeprecationWarning + ) return self.components def getParent(self): - warnings.warn("'Glyph.getParent()': use 'Glyph.font'", - DeprecationWarning) + warnings.warn("'Glyph.getParent()': use 'Glyph.font'", DeprecationWarning) return self.font def readGlyphFromString(self, glifData): - warnings.warn(("'Glyph.readGlyphFromString()': use " - "'Glyph.loadFromGLIF()'"), - DeprecationWarning) + warnings.warn( + ("'Glyph.readGlyphFromString()': use " "'Glyph.loadFromGLIF()'"), + DeprecationWarning, + ) return self.loadFromGLIF(glifData) def writeGlyphToString(self, glyphFormatVersion=2): - warnings.warn(("'Glyph.writeGlyphToString()': use " - "'Glyph.dumpToGLIF()'"), - DeprecationWarning) + warnings.warn( + ("'Glyph.writeGlyphToString()': use " "'Glyph.dumpToGLIF()'"), + DeprecationWarning, + ) return self.dumpToGLIF(glyphFormatVersion) @@ -386,26 +417,29 @@ def writeGlyphToString(self, glyphFormatVersion=2): class RemovedGuideline(RemovedBase): - pass class DeprecatedGuideline(DeprecatedBase, DeprecatedTransformation): - def _generateIdentifier(self): - warnings.warn(("'Guideline._generateIdentifier()': " - "use 'Guideline._getIdentifier()'"), DeprecationWarning) + warnings.warn( + ("'Guideline._generateIdentifier()': " "use 'Guideline._getIdentifier()'"), + DeprecationWarning, + ) return self._getIdentifier() def generateIdentifier(self): - warnings.warn(("'Guideline.generateIdentifier()': " - "use 'Guideline.getIdentifier()'"), DeprecationWarning) + warnings.warn( + ("'Guideline.generateIdentifier()': " "use 'Guideline.getIdentifier()'"), + DeprecationWarning, + ) return self.getIdentifier() def getParent(self): - warnings.warn(("'Guideline.getParent()': use 'Guideline.glyph'" - " or 'Guideline.font'"), - DeprecationWarning) + warnings.warn( + ("'Guideline.getParent()': use 'Guideline.glyph'" " or 'Guideline.font'"), + DeprecationWarning, + ) glyph = self.glyph if glyph is not None: return glyph @@ -416,24 +450,23 @@ def getParent(self): # = Lib = # ======= -class RemovedLib(RemovedBase): +class RemovedLib(RemovedBase): pass class DeprecatedLib(object): - def getParent(self): - warnings.warn("'Lib.getParent()': use 'Lib.glyph' or 'Lib.font'", - DeprecationWarning) + warnings.warn( + "'Lib.getParent()': use 'Lib.glyph' or 'Lib.font'", DeprecationWarning + ) glyph = self.glyph if glyph is not None: return glyph return self.font def setChanged(self): - warnings.warn("'Lib.setChanged': use Lib.changed()", - DeprecationWarning) + warnings.warn("'Lib.setChanged': use Lib.changed()", DeprecationWarning) self.changed() @@ -441,21 +474,18 @@ def setChanged(self): # = Groups = # ========== -class RemovedGroups(RemovedBase): +class RemovedGroups(RemovedBase): pass class DeprecatedGroups(object): - def getParent(self): - warnings.warn("'Groups.getParent()': use 'Groups.font'", - DeprecationWarning) + warnings.warn("'Groups.getParent()': use 'Groups.font'", DeprecationWarning) return self.font def setChanged(self): - warnings.warn("'Groups.setChanged': use Groups.changed()", - DeprecationWarning) + warnings.warn("'Groups.setChanged': use Groups.changed()", DeprecationWarning) self.changed() @@ -463,8 +493,8 @@ def setChanged(self): # = Kerning = # =========== -class RemovedKerning(object): +class RemovedKerning(object): @staticmethod def setParent(parent): raise RemovedError("'Kerning.setParent()'") @@ -506,8 +536,9 @@ def combine(kerningDicts, overwriteExisting=True): raise RemovedError("Kerning.combine()") @staticmethod - def eliminate(leftGlyphsToEliminate=None, - rightGlyphsToEliminate=None, analyzeOnly=False): + def eliminate( + leftGlyphsToEliminate=None, rightGlyphsToEliminate=None, analyzeOnly=False + ): raise RemovedError("Kerning.eliminate()") @staticmethod @@ -515,26 +546,21 @@ def occurrenceCount(glyphsToCount): raise RemovedError("Kerning.occurrenceCount()") @staticmethod - def implodeClasses(leftClassDict=None, - rightClassDict=None, analyzeOnly=False): + def implodeClasses(leftClassDict=None, rightClassDict=None, analyzeOnly=False): raise RemovedError("Kerning.implodeClasses()") @staticmethod - def explodeClasses(leftClassDict=None, - rightClassDict=None, analyzeOnly=False): + def explodeClasses(leftClassDict=None, rightClassDict=None, analyzeOnly=False): raise RemovedError("Kerning.explodeClasses()") class DeprecatedKerning(object): - def setChanged(self): - warnings.warn("'Kerning.setChanged': use Kerning.changed()", - DeprecationWarning) + warnings.warn("'Kerning.setChanged': use Kerning.changed()", DeprecationWarning) self.changed() def getParent(self): - warnings.warn("'Kerning.getParent()': use 'Kerning.font'", - DeprecationWarning) + warnings.warn("'Kerning.getParent()': use 'Kerning.font'", DeprecationWarning) return self.font @@ -542,16 +568,14 @@ def getParent(self): # = Info = # ======== -class RemovedInfo(RemovedBase): +class RemovedInfo(RemovedBase): pass class DeprecatedInfo(DeprecatedBase): - def getParent(self): - warnings.warn("'Info.getParent()': use 'Info.font'", - DeprecationWarning) + warnings.warn("'Info.getParent()': use 'Info.font'", DeprecationWarning) return self.font @@ -559,16 +583,14 @@ def getParent(self): # = Image = # ========= -class RemovedImage(RemovedBase): +class RemovedImage(RemovedBase): pass class DeprecatedImage(DeprecatedBase): - def getParent(self): - warnings.warn("'Image.getParent()': use 'Image.glyph'", - DeprecationWarning) + warnings.warn("'Image.getParent()': use 'Image.glyph'", DeprecationWarning) return self.glyph @@ -576,18 +598,16 @@ def getParent(self): # = Features = # ============ -class RemovedFeatures(RemovedBase): +class RemovedFeatures(RemovedBase): @staticmethod def round(): raise RemovedError("'Features.round()'") class DeprecatedFeatures(DeprecatedBase): - def getParent(self): - warnings.warn("'Features.getParent()': use 'Features.font'", - DeprecationWarning) + warnings.warn("'Features.getParent()': use 'Features.font'", DeprecationWarning) return self.font @@ -595,16 +615,14 @@ def getParent(self): # = Layer = # ========= -class RemovedLayer(RemovedBase): +class RemovedLayer(RemovedBase): pass class DeprecatedLayer(DeprecatedBase): - def getParent(self): - warnings.warn("'Layer.getParent()': use 'Layer.font'", - DeprecationWarning) + warnings.warn("'Layer.getParent()': use 'Layer.font'", DeprecationWarning) return self.font @@ -612,8 +630,8 @@ def getParent(self): # = Font = # ======== -class RemovedFont(RemovedBase): +class RemovedFont(RemovedBase): @staticmethod def getParent(): raise RemovedError("'Font.getParent()'") @@ -632,33 +650,36 @@ def getGlyphNameToFileNameFunc(): class DeprecatedFont(DeprecatedBase): - def _get_fileName(self): - warnings.warn("'Font.fileName': use os.path.basename(Font.path)", - DeprecationWarning) + warnings.warn( + "'Font.fileName': use os.path.basename(Font.path)", DeprecationWarning + ) return self.path fileName = property(_get_fileName, doc="Deprecated Font.fileName") def getWidth(self, glyphName): - warnings.warn("'Font.getWidth(): use Font[glyphName].width'", - DeprecationWarning) + warnings.warn( + "'Font.getWidth(): use Font[glyphName].width'", DeprecationWarning + ) return self[glyphName].width def getGlyph(self, glyphName): - warnings.warn("'Font.getGlyph(): use Font[glyphName]'", - DeprecationWarning) + warnings.warn("'Font.getGlyph(): use Font[glyphName]'", DeprecationWarning) return self[glyphName] def _get_selection(self): - warnings.warn("'Font.selection: use Font.selectedGlyphNames'", - DeprecationWarning) + warnings.warn( + "'Font.selection: use Font.selectedGlyphNames'", DeprecationWarning + ) return self.selectedGlyphNames def _set_selection(self, glyphNames): - warnings.warn("'Font.selection: use Font.selectedGlyphNames'", - DeprecationWarning) + warnings.warn( + "'Font.selection: use Font.selectedGlyphNames'", DeprecationWarning + ) self.selectedGlyphNames = glyphNames - selection = property(_get_selection, _set_selection, - doc="Deprecated Font.selection") + selection = property( + _get_selection, _set_selection, doc="Deprecated Font.selection" + ) diff --git a/Lib/fontParts/base/features.py b/Lib/fontParts/base/features.py index fd2c8c59..1219b219 100644 --- a/Lib/fontParts/base/features.py +++ b/Lib/fontParts/base/features.py @@ -4,7 +4,6 @@ class BaseFeatures(BaseObject, DeprecatedFeatures, RemovedFeatures): - copyAttributes = ("text",) def _reprContents(self): @@ -31,7 +30,9 @@ def _get_font(self): def _set_font(self, font): if self._font is not None and self._font() != font: - raise AssertionError("font for features already set and is not same as font") + raise AssertionError( + "font for features already set and is not same as font" + ) if font is not None: font = reference(font) self._font = font @@ -47,7 +48,7 @@ def _set_font(self, font): `_ text representing the features. It must be a :ref:`type-string`. - """ + """, ) def _get_base_text(self): diff --git a/Lib/fontParts/base/font.py b/Lib/fontParts/base/font.py index d9e02008..8f1a7006 100644 --- a/Lib/fontParts/base/font.py +++ b/Lib/fontParts/base/font.py @@ -1,9 +1,7 @@ # pylint: disable=C0103, W0613 from __future__ import annotations import os -from typing import ( - TYPE_CHECKING, Any, Generic, List, Optional, Tuple, Type, Union -) +from typing import TYPE_CHECKING, Any, Generic, List, Optional, Tuple, Type, Union from fontParts.base.errors import FontPartsError from fontParts.base.base import dynamicProperty, InterpolationMixin @@ -18,8 +16,9 @@ PairCollectionType, TransformationType, KerningDictType, - ReverseComponentMappingType + ReverseComponentMappingType, ) + if TYPE_CHECKING: from fontParts.base.info import BaseInfo from fontParts.base.groups import BaseGroups @@ -31,10 +30,7 @@ from fontParts.base.guideline import BaseGuideline -class BaseFont(_BaseGlyphVendor, - InterpolationMixin, - DeprecatedFont, - RemovedFont): +class BaseFont(_BaseGlyphVendor, InterpolationMixin, DeprecatedFont, RemovedFont): """Represent the basis for a font object. Instances of this class are almost always created with one of the @@ -54,11 +50,14 @@ class BaseFont(_BaseGlyphVendor, """ - def __init__(self, - pathOrObject: Optional[Union[str, 'BaseFont']] = None, - showInterface: bool = True) -> None: - super(BaseFont, self).__init__(pathOrObject=pathOrObject, - showInterface=showInterface) + def __init__( + self, + pathOrObject: Optional[Union[str, "BaseFont"]] = None, + showInterface: bool = True, + ) -> None: + super(BaseFont, self).__init__( + pathOrObject=pathOrObject, showInterface=showInterface + ) def _reprContents(self) -> List[str]: contents: List[str] = [ @@ -80,7 +79,7 @@ def _reprContents(self) -> List[str]: "lib", "layerOrder", "defaultLayerName", - "glyphOrder" + "glyphOrder", ) def copy(self) -> BaseFont: @@ -142,10 +141,12 @@ def copyData(self, source: BaseFont) -> None: # Initialize - def _init(self, - pathOrObject: Optional[Union[str, BaseFont]], - showInterface: bool, - **kwargs: Any) -> None: + def _init( + self, + pathOrObject: Optional[Union[str, BaseFont]], + showInterface: bool, + **kwargs: Any, + ) -> None: r"""Initialize the native font object. This method is the environment implementation @@ -192,7 +193,7 @@ def _init(self, >>> print(font.path) "/path/to/my/font.ufo" - """ + """, ) def _get_base_path(self) -> Optional[str]: @@ -224,11 +225,13 @@ def _get_path(self, **kwargs: Any) -> Optional[str]: # save - def save(self, - path: Optional[str] = None, - showProgress: bool = False, - formatVersion: Optional[int] = None, - fileStructure: Optional[str] = None) -> None: + def save( + self, + path: Optional[str] = None, + showProgress: bool = False, + formatVersion: Optional[int] = None, + fileStructure: Optional[str] = None, + ) -> None: """Save the font to the specified path. :param path: The path to which the font should be saved. @@ -269,25 +272,31 @@ def save(self, """ if path is None and self.path is None: - raise IOError(("The font cannot be saved because no file " - "location has been given.")) + raise IOError( + ("The font cannot be saved because no file " "location has been given.") + ) if path is not None: path = normalizers.normalizeFilePath(path) showProgress = bool(showProgress) if formatVersion is not None: - formatVersion = normalizers.normalizeFileFormatVersion( - formatVersion) + formatVersion = normalizers.normalizeFileFormatVersion(formatVersion) if fileStructure is not None: fileStructure = normalizers.normalizeFileStructure(fileStructure) - self._save(path=path, showProgress=showProgress, - formatVersion=formatVersion, fileStructure=fileStructure) - - def _save(self, - path: Optional[str], - showProgress: bool, - formatVersion: Optional[float], - fileStructure: Optional[str], - **kwargs: Any) -> None: + self._save( + path=path, + showProgress=showProgress, + formatVersion=formatVersion, + fileStructure=fileStructure, + ) + + def _save( + self, + path: Optional[str], + showProgress: bool, + formatVersion: Optional[float], + fileStructure: Optional[str], + **kwargs: Any, + ) -> None: r"""Save the native font to the specified path. This is the environment implementation of :meth:`BaseFont.save`. @@ -401,10 +410,9 @@ def generateFormatToExtension(format: str, fallbackFormat: str) -> str: ) return formatToExtension.get(format, fallbackFormat) - def generate(self, - format: str, - path: Optional[str] = None, - **environmentOptions: Any) -> None: + def generate( + self, format: str, path: Optional[str] = None, **environmentOptions: Any + ) -> None: r"""Generate the font in another format. This method converts the font to the specified format and saves @@ -440,6 +448,7 @@ def generate(self, """ import warnings + if format is None: raise ValueError("The format must be defined when generating.") elif not isinstance(format, str): @@ -448,29 +457,37 @@ def generate(self, for key, value in environmentOptions.items(): valid = self._isValidGenerateEnvironmentOption(key) if not valid: - warnings.warn("The %s argument is not supported " - "in this environment." % key, UserWarning) + warnings.warn( + "The %s argument is not supported " "in this environment." % key, + UserWarning, + ) env[key] = value environmentOptions = env ext = self.generateFormatToExtension(format, "." + format) if path is None and self.path is None: - raise IOError(("The file cannot be generated because an " - "output path was not defined.")) + raise IOError( + ( + "The file cannot be generated because an " + "output path was not defined." + ) + ) elif path is None: path = os.path.splitext(self.path)[0] path += ext elif os.path.isdir(path): if self.path is None: - raise IOError(("The file cannot be generated because " - "the file does not have a path.")) + raise IOError( + ( + "The file cannot be generated because " + "the file does not have a path." + ) + ) fileName = os.path.basename(self.path) fileName += ext path = os.path.join(path, fileName) path = normalizers.normalizeFilePath(path) return self._generate( - format=format, - path=path, - environmentOptions=environmentOptions + format=format, path=path, environmentOptions=environmentOptions ) @staticmethod @@ -493,11 +510,13 @@ def _isValidGenerateEnvironmentOption(name: str) -> bool: """ return False - def _generate(self, - format: str, - path: Optional[str], - environmentOptions: dict, - **kwargs: object) -> None: + def _generate( + self, + format: str, + path: Optional[str], + environmentOptions: dict, + **kwargs: object, + ) -> None: """Generate the native font in another format. This is the environment implementation @@ -545,7 +564,7 @@ def _generate(self, >>> font.info.familyName "My Family" - """ + """, ) def _get_base_info(self) -> BaseInfo: @@ -584,7 +603,7 @@ def _get_info(self) -> BaseInfo: >>> font.groups["myGroup"] ["A", "B", "C"] - """ + """, ) def _get_base_groups(self) -> BaseGroups: @@ -624,7 +643,7 @@ def _get_groups(self) -> BaseGroups: >>> font.kerning["A", "B"] -100 - """ + """, ) def _get_base_kerning(self) -> BaseKerning: @@ -655,7 +674,7 @@ def getFlatKerning(self) -> KerningDictType: :return: A :class:`dict` of the font's :class:`BaseKerning` keys mapped to their respective values. - """ + """ return self._getFlatKerning() def _getFlatKerning(self) -> KerningDictType: @@ -723,7 +742,7 @@ def kerningSortKeyFunc(pair): >>> font.features.text "include(features/substitutions.fea);" - """ + """, ) def _get_base_features(self) -> BaseFeatures: @@ -763,7 +782,7 @@ def _get_features(self) -> BaseFeatures: >>> font.lib["org.robofab.hello"] "world" - """ + """, ) def _get_base_lib(self) -> BaseLib: @@ -808,7 +827,7 @@ def _get_lib(self) -> BaseLib: >>> font.tempLib["org.robofab.hello"] "world" - """ + """, ) def _get_base_tempLib(self) -> BaseLib: @@ -853,7 +872,7 @@ def _get_tempLib(self) -> BaseLib: "My Layer 1" "My Layer 2" - """ + """, ) def _get_base_layers(self) -> Tuple[BaseLayer, ...]: @@ -899,7 +918,7 @@ def _get_layers(self, **kwargs: Any) -> Tuple[BaseLayer, ...]: >>> font.layerOrder ("My Layer 2", "My Layer 1") - """ + """, ) def _get_base_layerOrder(self) -> Tuple[str, ...]: @@ -930,9 +949,7 @@ def _get_layerOrder(self, **kwargs: Any) -> Tuple[str, ...]: """ self.raiseNotImplementedError() - def _set_layerOrder(self, - value: CollectionType[str], - **kwargs: Any) -> None: + def _set_layerOrder(self, value: CollectionType[str], **kwargs: Any) -> None: r"""Set the order of the layers in the native font. This is the environment implementation of the @@ -975,7 +992,7 @@ def _setFontInLayer(self, layer: BaseLayer) -> None: >>> font.defaultLayerName "My Layer 2" - """ + """, ) def _get_base_defaultLayerName(self) -> str: @@ -1037,7 +1054,7 @@ def _set_defaultLayerName(self, value: str, **kwargs: Any) -> None: >>> layer = font.defaultLayer >>> font.defaultLayer = otherLayer - """ + """, ) def _get_base_defaultLayer(self) -> BaseLayer: @@ -1135,10 +1152,9 @@ def _getLayer(self, name: str, **kwargs: Any) -> BaseLayer: # new - def newLayer(self, - name: str, - color: Optional[QuadrupleCollectionType[IntFloatType]] = None - ) -> BaseLayer: + def newLayer( + self, name: str, color: Optional[QuadrupleCollectionType[IntFloatType]] = None + ) -> BaseLayer: """Create a new layer in the font. :param name: The name of the new layer to create. @@ -1163,10 +1179,12 @@ def newLayer(self, self._setFontInLayer(layer) return layer - def _newLayer(self, - name: str, - color: Optional[QuadrupleCollectionType[IntFloatType]], - **kwargs: Any) -> BaseLayer: + def _newLayer( + self, + name: str, + color: Optional[QuadrupleCollectionType[IntFloatType]], + **kwargs: Any, + ) -> BaseLayer: r"""Create a new layer in the native font. This is the environment implementation of @@ -1230,9 +1248,7 @@ def _removeLayer(self, name: str, **kwargs: Any) -> None: # insert - def insertLayer(self, - layer: BaseLayer, - name: Optional[str] = None) -> BaseLayer: + def insertLayer(self, layer: BaseLayer, name: Optional[str] = None) -> BaseLayer: """Insert a specified layer into the font. This method will not insert a layer directly, but rather create @@ -1258,9 +1274,7 @@ def insertLayer(self, self.removeLayer(normalizedName) return self._insertLayer(layer, name=normalizedName) - def _insertLayer(self, layer: BaseLayer, - name: str, - **kwargs: Any) -> BaseLayer: + def _insertLayer(self, layer: BaseLayer, name: str, **kwargs: Any) -> BaseLayer: r"""Insert a specified layer into the native font. This is the environment implementation of :meth:`BaseFont.insertLayer`. @@ -1314,9 +1328,7 @@ def duplicateLayer(self, layerName: str, newLayerName: str) -> BaseLayer: layerOrder = self.layerOrder layerName = normalizers.normalizeLayerName(layerName) if layerName not in layerOrder: - raise ValueError( - "No layer with the name '%s' exists." % layerName - ) + raise ValueError("No layer with the name '%s' exists." % layerName) newLayerName = normalizers.normalizeLayerName(newLayerName) if newLayerName in layerOrder: raise ValueError( @@ -1372,14 +1384,10 @@ def swapLayerNames(self, layerName: str, otherLayerName: str) -> None: layerOrder = self.layerOrder layerName = normalizers.normalizeLayerName(layerName) if layerName not in layerOrder: - raise ValueError( - "No layer with the name '%s' exists." % layerName - ) + raise ValueError("No layer with the name '%s' exists." % layerName) otherLayerName = normalizers.normalizeLayerName(otherLayerName) if otherLayerName not in layerOrder: - raise ValueError( - "No layer with the name '%s' exists." % otherLayerName - ) + raise ValueError("No layer with the name '%s' exists." % otherLayerName) self._swapLayerNames(layerName, otherLayerName) def _swapLayerNames(self, layerName: str, otherLayerName: str) -> None: @@ -1401,6 +1409,7 @@ def _swapLayerNames(self, layerName: str, otherLayerName: str) -> None: """ import random + layer1 = self.getLayer(layerName) layer2 = self.getLayer(otherLayerName) # make a temporary name and assign it to @@ -1511,9 +1520,7 @@ def _removeGlyph(self, name: str, **kwargs: Any) -> None: layer = self.defaultLayer layer.removeGlyph(name) - def __setitem__(self, - name: str, - glyph: BaseGlyph) -> BaseGlyph: + def __setitem__(self, name: str, glyph: BaseGlyph) -> BaseGlyph: """Insert the specified glyph into the font. Example:: @@ -1558,7 +1565,7 @@ def __setitem__(self, ["C", "B", "A"] >>> font.glyphOrder = ("A", "B", "C") - """ + """, ) def _get_base_glyphOrder(self) -> Tuple[str]: @@ -1701,7 +1708,7 @@ def _setFontInGuideline(self, guideline): 45 90 - """ + """, ) def _get_guidelines(self) -> Tuple[BaseGuideline, ...]: @@ -1718,8 +1725,9 @@ def _get_guidelines(self) -> Tuple[BaseGuideline, ...]: Subclasses may override this method. """ - return tuple(self._getitem__guidelines(i) - for i in range(self._len__guidelines())) + return tuple( + self._getitem__guidelines(i) for i in range(self._len__guidelines()) + ) def _len__guidelines(self) -> int: return self._lenGuidelines() @@ -1769,13 +1777,14 @@ def _getGuidelineIndex(self, guideline: BaseGuideline) -> int: return i raise FontPartsError("The guideline could not be found.") - def appendGuideline(self, - position: Optional[PairCollectionType[IntFloatType]] = None, - angle: Optional[float] = None, - name: Optional[str] = None, - color: Optional[QuadrupleCollectionType[IntFloatType]] = None, - guideline: Optional[BaseGuideline] = None - ) -> BaseGuideline: + def appendGuideline( + self, + position: Optional[PairCollectionType[IntFloatType]] = None, + angle: Optional[float] = None, + name: Optional[str] = None, + color: Optional[QuadrupleCollectionType[IntFloatType]] = None, + guideline: Optional[BaseGuideline] = None, + ) -> BaseGuideline: """Append a new guideline to the font. This method will create a new :class:`BaseGuideline` with the @@ -1818,8 +1827,7 @@ def appendGuideline(self, color = normalizedGuideline.color if normalizedGuideline.identifier is not None: existing = set( - [g.identifier for g in self.guidelines - if g.identifier is not None] + [g.identifier for g in self.guidelines if g.identifier is not None] ) if normalizedGuideline.identifier not in existing: identifier = normalizedGuideline.identifier @@ -1836,13 +1844,15 @@ def appendGuideline(self, newGuideline.font = self return newGuideline - def _appendGuideline(self, - position: Optional[PairCollectionType[IntFloatType]], - angle: Optional[float], - name: Optional[str], - color: Optional[QuadrupleCollectionType[IntFloatType]], - guideline: Optional[BaseGuideline], - **kwargs) -> BaseGuideline: + def _appendGuideline( + self, + position: Optional[PairCollectionType[IntFloatType]], + angle: Optional[float], + name: Optional[str], + color: Optional[QuadrupleCollectionType[IntFloatType]], + guideline: Optional[BaseGuideline], + **kwargs, + ) -> BaseGuideline: r"""Append a new guideline to the native font. This is the environment implementation of @@ -1867,8 +1877,7 @@ def _appendGuideline(self, """ self.raiseNotImplementedError() - def removeGuideline(self, - guideline: Union[int, BaseGuideline]) -> None: + def removeGuideline(self, guideline: Union[int, BaseGuideline]) -> None: """Remove a guideline from the font. :param guideline: A :class:`BaseGuideline` object or an integer @@ -1935,12 +1944,14 @@ def _clearGuidelines(self) -> None: # Interpolation # ------------- - def interpolate(self, - factor: TransformationType, - minFont: BaseFont, - maxFont: BaseFont, - round: bool = True, - suppressError: bool = True) -> None: + def interpolate( + self, + factor: TransformationType, + minFont: BaseFont, + maxFont: BaseFont, + round: bool = True, + suppressError: bool = True, + ) -> None: """Interpolate all possible data in the font. The interpolation occurs on a 0 to 1.0 range between `minFont` @@ -1970,27 +1981,34 @@ def interpolate(self, factor = normalizers.normalizeInterpolationFactor(factor) if not isinstance(minFont, BaseFont): raise TypeError( - ("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) % (self.__class__.__name__, minFont.__class__.__name__) ) if not isinstance(maxFont, BaseFont): raise TypeError( - ("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) % (self.__class__.__name__, maxFont.__class__.__name__) ) round = normalizers.normalizeBoolean(round) suppressError = normalizers.normalizeBoolean(suppressError) - self._interpolate(factor, minFont, maxFont, - round=round, suppressError=suppressError) - - def _interpolate(self, - factor: TransformationType, - minFont: BaseFont, - maxFont: BaseFont, - round: bool, - suppressError: bool) -> None: + self._interpolate( + factor, minFont, maxFont, round=round, suppressError=suppressError + ) + + def _interpolate( + self, + factor: TransformationType, + minFont: BaseFont, + maxFont: BaseFont, + round: bool, + suppressError: bool, + ) -> None: """Interpolate all possible data in the native font. This is the environment implementation of :meth:`BaseFont.interpolate`. @@ -2024,19 +2042,26 @@ def _interpolate(self, minLayer = minFont.getLayer(layerName) maxLayer = maxFont.getLayer(layerName) dstLayer = self.newLayer(layerName) - dstLayer.interpolate(factor, minLayer, maxLayer, - round=round, suppressError=suppressError) + dstLayer.interpolate( + factor, minLayer, maxLayer, round=round, suppressError=suppressError + ) if self.layerOrder: if ufoLib.DEFAULT_LAYER_NAME in self.layerOrder: self.defaultLayer = self.getLayer(ufoLib.DEFAULT_LAYER_NAME) else: self.defaultLayer = self.getLayer(self.layerOrder[0]) # kerning and groups - self.kerning.interpolate(factor, minFont.kerning, maxFont.kerning, - round=round, suppressError=suppressError) + self.kerning.interpolate( + factor, + minFont.kerning, + maxFont.kerning, + round=round, + suppressError=suppressError, + ) # info - self.info.interpolate(factor, minFont.info, maxFont.info, - round=round, suppressError=suppressError) + self.info.interpolate( + factor, minFont.info, maxFont.info, round=round, suppressError=suppressError + ) compatibilityReporterClass = FontCompatibilityReporter @@ -2065,9 +2090,9 @@ def isCompatible(self, other: BaseFont) -> Tuple[bool, str]: """ return super(BaseFont, self).isCompatible(other, BaseFont) - def _isCompatible(self, - other: BaseFont, - reporter: FontCompatibilityReporter) -> None: + def _isCompatible( + self, other: BaseFont, reporter: FontCompatibilityReporter + ) -> None: """Evaluate interpolation compatibility with another native font. This is the environment implementation of :meth:`BaseFont.isCompatible`. @@ -2093,11 +2118,13 @@ def _isCompatible(self, if len(guidelines1.difference(guidelines2)) != 0: reporter.warning = True reporter.guidelinesMissingFromFont2 = list( - guidelines1.difference(guidelines2)) + guidelines1.difference(guidelines2) + ) if len(guidelines2.difference(guidelines1)) != 0: reporter.warning = True reporter.guidelinesMissingInFont1 = list( - guidelines2.difference(guidelines1)) + guidelines2.difference(guidelines1) + ) # incompatible layers layers1 = set(font1.layerOrder) layers2 = set(font2.layerOrder) @@ -2229,12 +2256,13 @@ def _getCharacterMapping(self) -> CharacterMappingType: >>> layer.selectedLayers = someLayers - """ + """, ) def _get_base_selectedLayers(self) -> Tuple[BaseLayer, ...]: - selected = tuple(normalizers.normalizeLayer(layer) for - layer in self._get_selectedLayers()) + selected = tuple( + normalizers.normalizeLayer(layer) for layer in self._get_selectedLayers() + ) return selected def _get_selectedLayers(self) -> Tuple[BaseLayer, ...]: @@ -2293,12 +2321,14 @@ def _set_selectedLayers(self, value: List[BaseLayer]) -> None: >>> layer.selectedLayerNames = ["A", "B", "C"] - """ + """, ) def _get_base_selectedLayerNames(self) -> Tuple[str, ...]: - selected = tuple(normalizers.normalizeLayerName(name) for - name in self._get_selectedLayerNames()) + selected = tuple( + normalizers.normalizeLayerName(name) + for name in self._get_selectedLayerNames() + ) return selected def _get_selectedLayerNames(self) -> Tuple[str, ...]: @@ -2364,12 +2394,14 @@ def _set_selectedLayerNames(self, value: List[str]) -> None: >>> font.selectedGuidelines = [0, 2] - """ + """, ) def _get_base_selectedGuidelines(self) -> Tuple[BaseGuideline, ...]: - selected = tuple(normalizers.normalizeGuideline(guideline) for - guideline in self._get_selectedGuidelines()) + selected = tuple( + normalizers.normalizeGuideline(guideline) + for guideline in self._get_selectedGuidelines() + ) return selected def _get_selectedGuidelines(self) -> Tuple[BaseGuideline, ...]: diff --git a/Lib/fontParts/base/glyph.py b/Lib/fontParts/base/glyph.py index 9b68e35d..baa7ec94 100644 --- a/Lib/fontParts/base/glyph.py +++ b/Lib/fontParts/base/glyph.py @@ -20,7 +20,7 @@ SelectionMixin, dynamicProperty, interpolate, - FuzzyNumber + FuzzyNumber, ) from fontParts.base import normalizers from fontParts.base.compatibility import GlyphCompatibilityReporter @@ -35,8 +35,9 @@ IntFloatType, TransformationType, PenType, - PointPenType + PointPenType, ) + if TYPE_CHECKING: from fontParts.base.font import BaseFont from fontParts.base.lib import BaseLib @@ -48,12 +49,14 @@ from fontParts.base.image import BaseImage -class BaseGlyph(BaseObject, - TransformationMixin, - InterpolationMixin, - SelectionMixin, - DeprecatedGlyph, - RemovedGlyph): +class BaseGlyph( + BaseObject, + TransformationMixin, + InterpolationMixin, + SelectionMixin, + DeprecatedGlyph, + RemovedGlyph, +): """Represent the basis for a glyph object. This object will almost always be created by retrieving it from a @@ -68,7 +71,7 @@ class BaseGlyph(BaseObject, "height", "note", "markColor", - "lib" + "lib", ) def _reprContents(self) -> List[str]: @@ -158,7 +161,7 @@ def copyData(self: BaseGlyph, source: BaseGlyph) -> None: >>> layer = glyph.layer - """ + """, ) def _get_layer(self) -> Optional[BaseLayer]: @@ -184,7 +187,7 @@ def _set_layer(self, layer: Optional[BaseLayer]) -> None: >>> font = glyph.font - """ + """, ) def _get_font(self) -> Optional[BaseFont]: @@ -214,7 +217,7 @@ def _get_font(self) -> Optional[BaseFont]: "A" >>> glyph.name = "A.alt" - """ + """, ) def _get_base_name(self) -> str: @@ -286,7 +289,7 @@ def _set_name(self, value: str) -> None: >>> glyph.unicodes = [65, 66] >>> glyph.unicodes = [] - """ + """, ) def _get_base_unicodes(self) -> Tuple[int, ...]: @@ -369,7 +372,7 @@ def _set_unicodes(self, value: CollectionType[int]) -> None: >>> glyph.unicodes () - """ + """, ) def _get_base_unicode(self) -> Optional[int]: @@ -473,7 +476,7 @@ def _autoUnicodes(self) -> None: 500 >>> glyph.width = 200 - """ + """, ) def _get_base_width(self) -> IntFloatType: @@ -538,7 +541,7 @@ def _set_width(self, value: IntFloatType) -> None: 35 >>> glyph.leftMargin = 45 - """ + """, ) def _get_base_leftMargin(self) -> Optional[IntFloatType]: @@ -603,7 +606,7 @@ def _set_leftMargin(self, value: IntFloatType) -> None: 35 >>> glyph.rightMargin = 45 - """ + """, ) def _get_base_rightMargin(self) -> Optional[IntFloatType]: @@ -672,7 +675,7 @@ def _set_rightMargin(self, value: IntFloatType) -> None: 500 >>> glyph.height = 200 - """ + """, ) def _get_base_height(self) -> IntFloatType: @@ -733,7 +736,7 @@ def _set_height(self, value: IntFloatType) -> None: 35 >>> glyph.bottomMargin = 45 - """ + """, ) def _get_base_bottomMargin(self) -> Optional[IntFloatType]: @@ -797,7 +800,7 @@ def _set_bottomMargin(self, value: IntFloatType) -> None: >>> glyph.topMargin 35 >>> glyph.topMargin = 45 - """ + """, ) def _get_base_topMargin(self) -> Optional[IntFloatType]: @@ -884,10 +887,9 @@ def getPointPen(self) -> PointPenType: """ self.raiseNotImplementedError() - def draw(self, - pen: PenType, - contours: bool = True, - components: bool = True) -> None: + def draw( + self, pen: PenType, contours: bool = True, components: bool = True + ) -> None: """Draw the glyph's outline data to the given pen object. :param pen: The :class:`~fontTools.pens.basePen.AbstractPen` subclass @@ -911,10 +913,9 @@ def draw(self, for component in self.components: component.draw(pen) - def drawPoints(self, - pen: PointPenType, - contours: bool = True, - components: bool = True) -> None: + def drawPoints( + self, pen: PointPenType, contours: bool = True, components: bool = True + ) -> None: """Draw the glyph's outline data to the given point pen object. :param pen: The :class:`~fontTools.pens.pointPen.AbstractPointPen` @@ -942,12 +943,14 @@ def drawPoints(self, # Contour, Component and Anchor Interaction # ----------------------------------------- - def clear(self, - contours: bool = True, - components: bool = True, - anchors: bool = True, - guidelines: bool = True, - image: bool = True) -> None: + def clear( + self, + contours: bool = True, + components: bool = True, + anchors: bool = True, + guidelines: bool = True, + image: bool = True, + ) -> None: """Clear the glyph data. This will clear: @@ -978,15 +981,22 @@ def clear(self, >>> glyph.clear(guidelines=False) """ - self._clear(contours=contours, components=components, - anchors=anchors, guidelines=guidelines, image=image) + self._clear( + contours=contours, + components=components, + anchors=anchors, + guidelines=guidelines, + image=image, + ) - def _clear(self, - contours: bool, - components: bool, - anchors: bool, - guidelines: bool, - image: bool) -> None: + def _clear( + self, + contours: bool, + components: bool, + anchors: bool, + guidelines: bool, + image: bool, + ) -> None: """Clear the native glyph data. This is the environment implementation of :meth:`BaseGlyph.clear`. @@ -1013,9 +1023,11 @@ def _clear(self, if image: self.clearImage() - def appendGlyph(self, - other: BaseGlyph, - offset: Optional[PairCollectionType[IntFloatType]] = None) -> None: + def appendGlyph( + self, + other: BaseGlyph, + offset: Optional[PairCollectionType[IntFloatType]] = None, + ) -> None: """Append data from `other` to new objects in the glyph. This will append: @@ -1042,9 +1054,9 @@ def appendGlyph(self, normalizedOffset = normalizers.normalizeTransformationOffset(offset) self._appendGlyph(other, normalizedOffset) - def _appendGlyph(self, - other: BaseGlyph, - offset: PairCollectionType[IntFloatType]) -> None: + def _appendGlyph( + self, other: BaseGlyph, offset: PairCollectionType[IntFloatType] + ) -> None: """Append data from `other` to new objects in the native glyph. This is the environment implementation of :meth:`BaseGlyph.appendGlyph`. @@ -1087,7 +1099,7 @@ def _setGlyphInContour(self, contour: BaseContour) -> None: >>> contours = glyph.contours - """ + """, ) def _get_contours(self) -> Tuple[BaseContour, ...]: @@ -1204,9 +1216,11 @@ def _getContourIndex(self, contour: BaseContour) -> int: return i raise FontPartsError("The contour could not be found.") - def appendContour(self, - contour: BaseContour, - offset: Optional[PairCollectionType[IntFloatType]] = None) -> BaseContour: + def appendContour( + self, + contour: BaseContour, + offset: Optional[PairCollectionType[IntFloatType]] = None, + ) -> BaseContour: """Append the given contour's data to the glyph. :param contour: The :class:`BaseContour` instace containing the source @@ -1228,10 +1242,12 @@ def appendContour(self, normalizedOffset = normalizers.normalizeTransformationOffset(offset) return self._appendContour(normalizedContour, normalizedOffset) - def _appendContour(self, - contour: BaseContour, - offset: PairCollectionType[IntFloatType], - **kwargs: Any) -> BaseContour: + def _appendContour( + self, + contour: BaseContour, + offset: PairCollectionType[IntFloatType], + **kwargs: Any, + ) -> BaseContour: r"""Append the given contour's data to the native glyph. This is the environment implementation of :meth:`BaseGlyph.appendContour`. @@ -1368,7 +1384,7 @@ def _setGlyphInComponent(self, component: BaseComponent) -> None: >>> components = glyph.components - """ + """, ) def _get_components(self) -> Tuple[BaseComponent, ...]: @@ -1384,8 +1400,9 @@ def _get_components(self) -> Tuple[BaseComponent, ...]: Subclasses may override this method. """ - return tuple(self._getitem__components(i) for - i in range(self._len__components())) + return tuple( + self._getitem__components(i) for i in range(self._len__components()) + ) def _len__components(self) -> int: return self._lenComponents() @@ -1436,12 +1453,13 @@ def _getComponentIndex(self, component: BaseComponent) -> int: return i raise FontPartsError("The component could not be found.") - def appendComponent(self, - baseGlyph: Optional[str] = None, - offset: Optional[PairCollectionType[IntFloatType]] = None, - scale: Optional[TransformationType] = None, - component: Optional[BaseComponent] = None - ) -> BaseComponent: + def appendComponent( + self, + baseGlyph: Optional[str] = None, + offset: Optional[PairCollectionType[IntFloatType]] = None, + scale: Optional[TransformationType] = None, + component: Optional[BaseComponent] = None, + ) -> BaseComponent: """Append a component to the glyph. If `baseGlyph`, `offset` or `scale` is specified, those values will be @@ -1486,8 +1504,9 @@ def appendComponent(self, if baseGlyph is None: baseGlyph = normalizedComponent.baseGlyph if normalizedComponent.identifier is not None: - existing = set(c.identifier for c in self.components - if c.identifier is not None) + existing = set( + c.identifier for c in self.components if c.identifier is not None + ) if normalizedComponent.identifier not in existing: identifier = normalizedComponent.identifier normalizedBaseGlyph = normalizers.normalizeGlyphName(baseGlyph) @@ -1508,14 +1527,16 @@ def appendComponent(self, return self._appendComponent( normalizedBaseGlyph, transformation=transformation, - identifier=normalizedIdentifier + identifier=normalizedIdentifier, ) - def _appendComponent(self, - baseGlyph: str, - transformation: Optional[SextupleCollectionType[IntFloatType]], - identifier: Optional[str], - **kwargs: Any) -> BaseComponent: + def _appendComponent( + self, + baseGlyph: str, + transformation: Optional[SextupleCollectionType[IntFloatType]], + identifier: Optional[str], + **kwargs: Any, + ) -> BaseComponent: r"""Append a component to the native glyph. This is the environment implementation of :meth:`BaseGlyph.appendComponent`. @@ -1641,7 +1662,7 @@ def _setGlyphInAnchor(self, anchor: BaseAnchor) -> None: >>> anchors = glyph.anchors - """ + """, ) def _get_anchors(self) -> Tuple[BaseAnchor, ...]: @@ -1654,8 +1675,7 @@ def _get_anchors(self) -> Tuple[BaseAnchor, ...]: Subclasses may override this method. """ - return tuple(self._getitem__anchors(i) for - i in range(self._len__anchors())) + return tuple(self._getitem__anchors(i) for i in range(self._len__anchors())) def _len__anchors(self) -> int: return self._lenAnchors() @@ -1705,11 +1725,13 @@ def _getAnchorIndex(self, anchor: BaseAnchor) -> int: return i raise FontPartsError("The anchor could not be found.") - def appendAnchor(self, - name: Optional[str] = None, - position: Optional[PairCollectionType[IntFloatType]] = None, - color: Optional[QuadrupleCollectionType[IntFloatType]] = None, - anchor: Optional[BaseAnchor] = None) -> BaseAnchor: + def appendAnchor( + self, + name: Optional[str] = None, + position: Optional[PairCollectionType[IntFloatType]] = None, + color: Optional[QuadrupleCollectionType[IntFloatType]] = None, + anchor: Optional[BaseAnchor] = None, + ) -> BaseAnchor: """Append an anchor to the glyph. If `name`, `position` or `color` are specified, those values will be @@ -1755,15 +1777,17 @@ def appendAnchor(self, normalizedName, position=normalizedPosition, color=normalizedColor, - identifier=normalizedIdentifier + identifier=normalizedIdentifier, ) - def _appendAnchor(self, # type: ignore[return] - name: str, - position: Optional[PairCollectionType[IntFloatType]], - color: Optional[QuadrupleCollectionType[IntFloatType]], - identifier: Optional[str], - **kwargs: Any) -> BaseAnchor: + def _appendAnchor( + self, # type: ignore[return] + name: str, + position: Optional[PairCollectionType[IntFloatType]], + color: Optional[QuadrupleCollectionType[IntFloatType]], + identifier: Optional[str], + **kwargs: Any, + ) -> BaseAnchor: r"""Append an anchor to the native glyph. This is the environment implementation of :meth:`BaseGlyph.appendAnchor`. @@ -1871,7 +1895,7 @@ def _setGlyphInGuideline(self, guideline: BaseGuideline) -> None: >>> guidelines = glyph.guidelines - """ + """, ) def _get_guidelines(self) -> Tuple[BaseGuideline, ...]: @@ -1887,8 +1911,9 @@ def _get_guidelines(self) -> Tuple[BaseGuideline, ...]: Subclasses may override this method. """ - return tuple(self._getitem__guidelines(i) - for i in range(self._len__guidelines())) + return tuple( + self._getitem__guidelines(i) for i in range(self._len__guidelines()) + ) def _len__guidelines(self) -> int: return self._lenGuidelines() @@ -1939,13 +1964,14 @@ def _getGuidelineIndex(self, guideline: BaseGuideline) -> int: return i raise FontPartsError("The guideline could not be found.") - def appendGuideline(self, - position: Optional[PairCollectionType[IntFloatType]] = None, - angle: Optional[IntFloatType] = None, - name: Optional[str] = None, - color: Optional[QuadrupleCollectionType[IntFloatType]] = None, - guideline: Optional[BaseGuideline] = None - ) -> BaseGuideline: + def appendGuideline( + self, + position: Optional[PairCollectionType[IntFloatType]] = None, + angle: Optional[IntFloatType] = None, + name: Optional[str] = None, + color: Optional[QuadrupleCollectionType[IntFloatType]] = None, + guideline: Optional[BaseGuideline] = None, + ) -> BaseGuideline: """Append a guideline to the glyph. If `name`, `position` or `color` are specified, those values will be @@ -1981,8 +2007,9 @@ def appendGuideline(self, if color is None: color = normalizedGuideline.color if normalizedGuideline.identifier is not None: - existing = set(g.identifier for g in self.guidelines - if g.identifier is not None) + existing = set( + g.identifier for g in self.guidelines if g.identifier is not None + ) if normalizedGuideline.identifier not in existing: identifier = normalizedGuideline.identifier normalizedPosition = normalizers.normalizeCoordinateTuple(position) @@ -1997,18 +2024,20 @@ def appendGuideline(self, normalizedAngle, name=normalizedName, color=normalizedColor, - identifier=normalizedIdentifier + identifier=normalizedIdentifier, ) newGuideline.glyph = self return newGuideline - def _appendGuideline(self, # type: ignore[return] - position: PairCollectionType[IntFloatType], - angle: IntFloatType, - name: Optional[str], - color: Optional[QuadrupleCollectionType[IntFloatType]], - identifier: Optional[str], - **kwargs: Any) -> BaseGuideline: + def _appendGuideline( + self, # type: ignore[return] + position: PairCollectionType[IntFloatType], + angle: IntFloatType, + name: Optional[str], + color: Optional[QuadrupleCollectionType[IntFloatType]], + identifier: Optional[str], + **kwargs: Any, + ) -> BaseGuideline: r"""Append a guideline to the native glyph. This is the environment implementation of :meth:`BaseGlyph.appendGuideline`. @@ -2158,9 +2187,7 @@ def correctDirection(self, trueType: bool = False) -> None: """ self._correctDirection(trueType=trueType) - def _correctDirection(self, - trueType: bool, - **kwargs: Any) -> None: + def _correctDirection(self, trueType: bool, **kwargs: Any) -> None: r"""Correct the winding direction of the native glyph's contours. This is the environment implementation @@ -2240,27 +2267,31 @@ def _autoContourOrder(self, **kwargs: Any) -> None: xThreshold = xTh if yThreshold is None or yThreshold > yTh: yThreshold = yTh - tempContourList.append(( - -len(contour.points), - -len(contour.segments), - xC, - yC, - -(width * height), - contour - )) + tempContourList.append( + ( + -len(contour.points), + -len(contour.segments), + xC, + yC, + -(width * height), + contour, + ) + ) xThreshold = xThreshold or 0.0 yThreshold = yThreshold or 0.0 for points, segments, x, y, surface, contour in tempContourList: - contourList.append(( - points, - segments, - FuzzyNumber(x, xThreshold), - FuzzyNumber(y, yThreshold), - surface, - contour - )) + contourList.append( + ( + points, + segments, + FuzzyNumber(x, xThreshold), + FuzzyNumber(y, yThreshold), + surface, + contour, + ) + ) contourList.sort() self.clearContours() @@ -2271,9 +2302,9 @@ def _autoContourOrder(self, **kwargs: Any) -> None: # Transformation # -------------- - def _transformBy(self, - matrix: SextupleCollectionType[IntFloatType], - **kwargs: Any) -> None: + def _transformBy( + self, matrix: SextupleCollectionType[IntFloatType], **kwargs: Any + ) -> None: r"""Transform the glyph according to the given matrix. :param matrix: The :ref:`type-transformation` to apply. @@ -2293,11 +2324,13 @@ def _transformBy(self, for guideline in self.guidelines: guideline.transformBy(matrix) - def scaleBy(self, - value: TransformationType, - origin: Optional[PairCollectionType[IntFloatType]] = None, - width: bool = False, - height: bool = False) -> None: + def scaleBy( + self, + value: TransformationType, + origin: Optional[PairCollectionType[IntFloatType]] = None, + width: bool = False, + height: bool = False, + ) -> None: """Scale the glyph according to the given values. :param value: The x and y values to scale the glyph by as @@ -2323,8 +2356,9 @@ def scaleBy(self, origin = (0, 0) normalizedOrigin = normalizers.normalizeCoordinateTuple(origin) if normalizedOrigin != (0, 0) and (width or height): - raise FontPartsError(("The origin must not be set when " - "scaling the width or height.")) + raise FontPartsError( + ("The origin must not be set when " "scaling the width or height.") + ) super(BaseGlyph, self).scaleBy(normalizedValue, origin=normalizedOrigin) sX, sY = normalizedValue if width: @@ -2362,9 +2396,9 @@ def _scaleHeightBy(self, value: IntFloatType) -> None: # Interpolation & Math # -------------------- - def toMathGlyph(self, - scaleComponentTransform: bool = True, - strict: bool = False) -> MathGlyph: + def toMathGlyph( + self, scaleComponentTransform: bool = True, strict: bool = False + ) -> MathGlyph: """Return the glyph as a `fontMath `_ :class:`MathGlyph` object. This method returns the glyph as an object following the `MathGlyph @@ -2386,9 +2420,7 @@ def toMathGlyph(self, scaleComponentTransform=scaleComponentTransform, strict=strict ) - def _toMathGlyph(self, - scaleComponentTransform: bool, - strict: bool) -> MathGlyph: + def _toMathGlyph(self, scaleComponentTransform: bool, strict: bool) -> MathGlyph: """Return the native glyph as a MathGlyph object. This is the environment implementation of :meth:`BaseGlyph.toMathGlyph`. @@ -2406,9 +2438,7 @@ def _toMathGlyph(self, """ mathGlyph = MathGlyph( - None, - scaleComponentTransform=scaleComponentTransform, - strict=strict + None, scaleComponentTransform=scaleComponentTransform, strict=strict ) pen = mathGlyph.getPointPen() self.drawPoints(pen) @@ -2418,7 +2448,7 @@ def _toMathGlyph(self, y=anchor.y, name=anchor.name, identifier=anchor.identifier, - color=anchor.color + color=anchor.color, ) mathGlyph.anchors.append(d) for guideline in self.guidelines: @@ -2428,7 +2458,7 @@ def _toMathGlyph(self, angle=guideline.angle, name=guideline.name, identifier=guideline.identifier, - color=guideline.color + color=guideline.color, ) mathGlyph.guidelines.append(d) mathGlyph.lib = deepcopy(self.lib) @@ -2439,9 +2469,9 @@ def _toMathGlyph(self, mathGlyph.note = self.note return mathGlyph - def fromMathGlyph(self, - mathGlyph: MathGlyph, - filterRedundantPoints: bool = True) -> BaseGlyph: + def fromMathGlyph( + self, mathGlyph: MathGlyph, filterRedundantPoints: bool = True + ) -> BaseGlyph: """Replace the glyph's data with the specified mathGlyph. This method returns the glyph as an object following the `MathGlyph @@ -2462,15 +2492,12 @@ def fromMathGlyph(self, """ return self._fromMathGlyph( - mathGlyph, - toThisGlyph=True, - filterRedundantPoints=filterRedundantPoints + mathGlyph, toThisGlyph=True, filterRedundantPoints=filterRedundantPoints ) - def _fromMathGlyph(self, - mathGlyph: MathGlyph, - toThisGlyph: bool, - filterRedundantPoints: bool) -> BaseGlyph: + def _fromMathGlyph( + self, mathGlyph: MathGlyph, toThisGlyph: bool, filterRedundantPoints: bool + ) -> BaseGlyph: """Replace native glyph data with the specified mathGlyph's data. This is the environment implementation of :meth:`BaseGlyph.fromMathGlyph`. @@ -2498,14 +2525,12 @@ def _fromMathGlyph(self, copied = copyClass() # populate pen = copied.getPointPen() - mathGlyph.drawPoints( - pen, filterRedundantPoints=filterRedundantPoints - ) + mathGlyph.drawPoints(pen, filterRedundantPoints=filterRedundantPoints) for anchor in mathGlyph.anchors: a = copied.appendAnchor( name=anchor.get("name"), position=(anchor["x"], anchor["y"]), - color=anchor["color"] + color=anchor["color"], ) identifier = anchor.get("identifier") if identifier is not None: @@ -2515,7 +2540,7 @@ def _fromMathGlyph(self, position=(guideline["x"], guideline["y"]), angle=guideline["angle"], name=guideline["name"], - color=guideline["color"] + color=guideline["color"], ) identifier = guideline.get("identifier") if identifier is not None: @@ -2545,9 +2570,9 @@ def __mul__(self, factor: TransformationType) -> BaseGlyph: """ mathGlyph = self._toMathGlyph(scaleComponentTransform=True, strict=False) result = mathGlyph * factor - copied = self._fromMathGlyph(result, - toThisGlyph=False, - filterRedundantPoints=True) + copied = self._fromMathGlyph( + result, toThisGlyph=False, filterRedundantPoints=True + ) return copied __rmul__ = __mul__ @@ -2568,9 +2593,9 @@ def __truediv__(self, factor: TransformationType) -> BaseGlyph: """ mathGlyph = self._toMathGlyph(scaleComponentTransform=True, strict=False) result = mathGlyph / factor - copied = self._fromMathGlyph(result, - toThisGlyph=False, - filterRedundantPoints=True) + copied = self._fromMathGlyph( + result, toThisGlyph=False, filterRedundantPoints=True + ) return copied # py2 support @@ -2590,9 +2615,9 @@ def __add__(self, other: BaseGlyph) -> BaseGlyph: selfMathGlyph = self._toMathGlyph(scaleComponentTransform=True, strict=False) otherMathGlyph = other._toMathGlyph(scaleComponentTransform=True, strict=False) result = selfMathGlyph + otherMathGlyph - copied = self._fromMathGlyph(result, - toThisGlyph=False, - filterRedundantPoints=True) + copied = self._fromMathGlyph( + result, toThisGlyph=False, filterRedundantPoints=True + ) return copied def __sub__(self, other: BaseGlyph) -> BaseGlyph: @@ -2612,17 +2637,19 @@ def __sub__(self, other: BaseGlyph) -> BaseGlyph: selfMathGlyph = self._toMathGlyph(scaleComponentTransform=True, strict=False) otherMathGlyph = other._toMathGlyph(scaleComponentTransform=True, strict=False) result = selfMathGlyph - otherMathGlyph - copied = self._fromMathGlyph(result, - toThisGlyph=False, - filterRedundantPoints=True) + copied = self._fromMathGlyph( + result, toThisGlyph=False, filterRedundantPoints=True + ) return copied - def interpolate(self, - factor: TransformationType, - minGlyph: BaseGlyph, - maxGlyph: BaseGlyph, - round: bool = True, - suppressError: bool = True) -> None: + def interpolate( + self, + factor: TransformationType, + minGlyph: BaseGlyph, + maxGlyph: BaseGlyph, + round: bool = True, + suppressError: bool = True, + ) -> None: """Interpolate all possible data in the glyph. :param factor: The interpolation value as a single :class:`int` @@ -2648,26 +2675,39 @@ def interpolate(self, """ normalizedFactor = normalizers.normalizeInterpolationFactor(factor) if not isinstance(minGlyph, BaseGlyph): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") - % (self.__class__.__name__, - minGlyph.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, minGlyph.__class__.__name__) + ) if not isinstance(maxGlyph, BaseGlyph): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") - % (self.__class__.__name__, - maxGlyph.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, maxGlyph.__class__.__name__) + ) round = normalizers.normalizeBoolean(round) suppressError = normalizers.normalizeBoolean(suppressError) - self._interpolate(normalizedFactor, minGlyph, maxGlyph, - round=round, suppressError=suppressError) - - def _interpolate(self, - factor: Tuple[IntFloatType, IntFloatType], - minGlyph: BaseGlyph, - maxGlyph: BaseGlyph, - round: bool, - suppressError: bool) -> None: + self._interpolate( + normalizedFactor, + minGlyph, + maxGlyph, + round=round, + suppressError=suppressError, + ) + + def _interpolate( + self, + factor: Tuple[IntFloatType, IntFloatType], + minGlyph: BaseGlyph, + maxGlyph: BaseGlyph, + round: bool, + suppressError: bool, + ) -> None: """Interpolate all possible data in the native glyph. This is the environment implementation of :meth:`BaseGlyph.interpolate`. @@ -2701,9 +2741,10 @@ def _interpolate(self, except IndexError: result = None if result is None and not suppressError: - raise FontPartsError(("Glyphs '%s' and '%s' could not be " - "interpolated.") - % (minGlyph.name, maxGlyph.name)) + raise FontPartsError( + ("Glyphs '%s' and '%s' could not be " "interpolated.") + % (minGlyph.name, maxGlyph.name) + ) if result is not None: if round: result = result.round() @@ -2712,10 +2753,9 @@ def _interpolate(self, compatibilityReporterClass = GlyphCompatibilityReporter @staticmethod - def _checkPairs(object1: Any, - object2: Any, - reporter: Any, - reporterObject: List[Any]) -> None: + def _checkPairs( + object1: Any, object2: Any, reporter: Any, reporterObject: List[Any] + ) -> None: compatibility = object1.isCompatible(object2)[1] if compatibility.fatal or compatibility.warning: if compatibility.fatal: @@ -2736,9 +2776,9 @@ def isCompatible(self, other: BaseGlyph) -> Tuple[bool, str]: """ return super(BaseGlyph, self).isCompatible(other, BaseGlyph) - def _isCompatible(self, - other: BaseGlyph, - reporter: GlyphCompatibilityReporter) -> None: + def _isCompatible( + self, other: BaseGlyph, reporter: GlyphCompatibilityReporter + ) -> None: """Evaluate interpolation compatibility with another native glyph. This is the environment implementation of :meth:`BaseGlyph.isCompatible`. @@ -2773,10 +2813,8 @@ def _isCompatible(self, reporter.componentCountDifference = True # component check component_diff: DiffType = [] - selfComponents = [component.baseGlyph - for component in glyph1.components] - otherComponents = [component.baseGlyph - for component in glyph2.components] + selfComponents = [component.baseGlyph for component in glyph1.components] + otherComponents = [component.baseGlyph for component in glyph2.components] for index, (left, right) in enumerate( zip_longest(selfComponents, otherComponents) ): @@ -2786,8 +2824,9 @@ def _isCompatible(self, if component_diff: reporter.warning = True reporter.componentDifferences = component_diff - if (not reporter.componentCountDifference - and set(selfComponents) == set(otherComponents)): + if not reporter.componentCountDifference and set(selfComponents) == set( + otherComponents + ): reporter.componentOrderDifference = True selfComponents_counted_set = Counter(selfComponents) @@ -2815,8 +2854,7 @@ def _isCompatible(self, # guideline check selfGuidelines: GuidelineListType = [] otherGuidelines: GuidelineListType = [] - for source, names in ((self, selfGuidelines), - (other, otherGuidelines)): + for source, names in ((self, selfGuidelines), (other, otherGuidelines)): for i, guideline in enumerate(source.guidelines): names.append((guideline.name, i)) guidelines1 = set(selfGuidelines) @@ -2824,11 +2862,13 @@ def _isCompatible(self, if len(guidelines1.difference(guidelines2)) != 0: reporter.warning = True reporter.guidelinesMissingFromGlyph2 = list( - guidelines1.difference(guidelines2)) + guidelines1.difference(guidelines2) + ) if len(guidelines2.difference(guidelines1)) != 0: reporter.warning = True reporter.guidelinesMissingFromGlyph1 = list( - guidelines2.difference(guidelines1)) + guidelines2.difference(guidelines1) + ) # anchor count if len(self.anchors) != len(glyph2.anchors): reporter.warning = True @@ -2837,28 +2877,26 @@ def _isCompatible(self, anchor_diff: DiffType = [] selfAnchors = [anchor.name for anchor in glyph1.anchors] otherAnchors = [anchor.name for anchor in glyph2.anchors] - for index, (left, right) in enumerate( - zip_longest(selfAnchors, otherAnchors)): + for index, (left, right) in enumerate(zip_longest(selfAnchors, otherAnchors)): if left != right: anchor_diff.append((index, left, right)) if anchor_diff: reporter.warning = True reporter.anchorDifferences = anchor_diff - if (not reporter.anchorCountDifference - and set(selfAnchors) == set(otherAnchors)): + if not reporter.anchorCountDifference and set(selfAnchors) == set( + otherAnchors + ): reporter.anchorOrderDifference = True selfAnchors_counted_set = Counter(selfAnchors) otherAnchors_counted_set = Counter(otherAnchors) - missing_from_glyph1 = (otherAnchors_counted_set - - selfAnchors_counted_set) + missing_from_glyph1 = otherAnchors_counted_set - selfAnchors_counted_set if missing_from_glyph1: reporter.anchorsMissingFromGlyph1 = sorted( missing_from_glyph1.elements() ) - missing_from_glyph2 = (selfAnchors_counted_set - - otherAnchors_counted_set) + missing_from_glyph2 = selfAnchors_counted_set - otherAnchors_counted_set if missing_from_glyph2: reporter.anchorsMissingFromGlyph2 = sorted( missing_from_glyph2.elements() @@ -2918,7 +2956,7 @@ def _pointInside(self, point: PairCollectionType[IntFloatType]) -> bool: >>> glyph.bounds (10, 30, 765, 643) - """ + """, ) def _get_base_bounds(self) -> Optional[PairType[IntFloatType]]: @@ -2960,7 +2998,7 @@ def _get_bounds(self) -> Optional[PairType[IntFloatType]]: >>> glyph.area 583 - """ + """, ) def _get_base_area(self) -> Optional[float]: @@ -3004,7 +3042,7 @@ def _get_area(self) -> Optional[float]: >>> glyphLayers = glyph.layers - """ + """, ) def _get_layers(self, **kwargs) -> Tuple[BaseGlyph, ...]: @@ -3061,8 +3099,7 @@ def _getLayer(self, name: str, **kwargs) -> BaseGlyph: for glyph in self.layers: if glyph.layer.name == name: return glyph - raise ValueError("No layer named '%s' in glyph '%s'." - % (name, self.name)) + raise ValueError("No layer named '%s' in glyph '%s'." % (name, self.name)) # new @@ -3162,7 +3199,7 @@ def _removeLayer(self, name: str, **kwargs: Any) -> None: :return: The :class:`BaseImage` instance belonging to the glyph. - """ + """, ) def _get_base_image(self) -> BaseImage: @@ -3185,12 +3222,14 @@ def _get_image(self) -> BaseImage: # type: ignore[return] """ self.raiseNotImplementedError() - def addImage(self, - path: Optional[str] = None, - data: Optional[bytes] = None, - scale: Optional[TransformationType] = None, - position: Optional[PairCollectionType[IntFloatType]] = None, - color: Optional[QuadrupleCollectionType[IntFloatType]] = None) -> BaseImage: + def addImage( + self, + path: Optional[str] = None, + data: Optional[bytes] = None, + scale: Optional[TransformationType] = None, + position: Optional[PairCollectionType[IntFloatType]] = None, + color: Optional[QuadrupleCollectionType[IntFloatType]] = None, + ) -> BaseImage: """Set the image in the glyph. The image data may be provided as either the `path` to an image file or @@ -3257,10 +3296,12 @@ def addImage(self, ) return self.image - def _addImage(self, # type: ignore[return] - data: bytes, - transformation: Optional[SextupleCollectionType[IntFloatType]], - color: Optional[QuadrupleCollectionType[IntFloatType]]) -> BaseImage: + def _addImage( + self, # type: ignore[return] + data: bytes, + transformation: Optional[SextupleCollectionType[IntFloatType]], + color: Optional[QuadrupleCollectionType[IntFloatType]], + ) -> BaseImage: """Set the image in the native glyph. Each environment may have different possible @@ -3322,7 +3363,7 @@ def _clearImage(self, **kwargs: Any) -> None: (1, 0, 0, 0.5) >>> glyph.markColor = None - """ + """, ) def _get_base_markColor(self) -> Optional[QuadrupleCollectionType[IntFloatType]]: @@ -3332,7 +3373,9 @@ def _get_base_markColor(self) -> Optional[QuadrupleCollectionType[IntFloatType]] normalizedValue = normalizers.normalizeColor(value) return Color(normalizedValue) - def _set_base_markColor(self, value: Optional[QuadrupleCollectionType[IntFloatType]]) -> None: + def _set_base_markColor( + self, value: Optional[QuadrupleCollectionType[IntFloatType]] + ) -> None: if value is not None: value = normalizers.normalizeColor(value) self._set_markColor(value) @@ -3355,7 +3398,9 @@ def _get_markColor(self) -> Optional[QuadrupleCollectionType[IntFloatType]]: # """ self.raiseNotImplementedError() - def _set_markColor(self, value: Optional[QuadrupleCollectionType[IntFloatType]]) -> None: + def _set_markColor( + self, value: Optional[QuadrupleCollectionType[IntFloatType]] + ) -> None: """Set the glyph's mark color. This is the environment implementation of @@ -3391,7 +3436,7 @@ def _set_markColor(self, value: Optional[QuadrupleCollectionType[IntFloatType]]) "P.B. said this looks 'awesome.'" >>> glyph.note = "P.B. said this looks 'AWESOME.'" - """ + """, ) def _get_base_note(self) -> Optional[str]: @@ -3456,7 +3501,7 @@ def _set_note(self, value: Optional[str]) -> None: >>> lib = glyph.lib - """ + """, ) def _get_base_lib(self) -> BaseLib: @@ -3502,7 +3547,7 @@ def _get_lib(self) -> BaseLib: # type: ignore[return] >>> tempLib = glyph.tempLib - """ + """, ) def _get_base_tempLib(self) -> BaseLib: @@ -3633,12 +3678,14 @@ def _dumpToGLIF(self, glyphFormatVersion: int) -> str: # type: ignore[return] >>> glyph.selectedContours = [0, 2] - """ + """, ) def _get_base_selectedContours(self) -> Tuple[BaseContour, ...]: - selected = tuple(normalizers.normalizeContour(contour) - for contour in self._get_selectedContours()) + selected = tuple( + normalizers.normalizeContour(contour) + for contour in self._get_selectedContours() + ) return selected def _get_selectedContours(self) -> Tuple[BaseContour, ...]: @@ -3658,8 +3705,9 @@ def _get_selectedContours(self) -> Tuple[BaseContour, ...]: """ return self._getSelectedSubObjects(self.contours) - def _set_base_selectedContours(self, - value: CollectionType[Union[int, BaseContour]]) -> None: + def _set_base_selectedContours( + self, value: CollectionType[Union[int, BaseContour]] + ) -> None: normalized = [] for i in value: if isinstance(i, int): @@ -3669,8 +3717,9 @@ def _set_base_selectedContours(self, normalized.append(i) self._set_selectedContours(normalized) - def _set_selectedContours(self, - value: CollectionType[Union[int, BaseContour]]) -> None: + def _set_selectedContours( + self, value: CollectionType[Union[int, BaseContour]] + ) -> None: """Set the selected contours in the glyph. This is the environment implementation of @@ -3711,12 +3760,14 @@ def _set_selectedContours(self, >>> glyph.selectedComponents = [0, 2] - """ + """, ) def _get_base_selectedComponents(self) -> Tuple[BaseComponent, ...]: - selected = tuple(normalizers.normalizeComponent(component) - for component in self._get_selectedComponents()) + selected = tuple( + normalizers.normalizeComponent(component) + for component in self._get_selectedComponents() + ) return selected def _get_selectedComponents(self) -> Tuple[BaseComponent, ...]: @@ -3736,8 +3787,9 @@ def _get_selectedComponents(self) -> Tuple[BaseComponent, ...]: """ return self._getSelectedSubObjects(self.components) - def _set_base_selectedComponents(self, - value: CollectionType[Union[int, BaseComponent]]) -> None: + def _set_base_selectedComponents( + self, value: CollectionType[Union[int, BaseComponent]] + ) -> None: normalized = [] for i in value: if isinstance(i, int): @@ -3747,8 +3799,9 @@ def _set_base_selectedComponents(self, normalized.append(i) self._set_selectedComponents(normalized) - def _set_selectedComponents(self, - value: CollectionType[Union[int, BaseComponent]]) -> None: + def _set_selectedComponents( + self, value: CollectionType[Union[int, BaseComponent]] + ) -> None: """Set the selected components in the glyph. This is the environment implementation of @@ -3789,12 +3842,14 @@ def _set_selectedComponents(self, >>> glyph.selectedAnchors = [0, 2] - """ + """, ) def _get_base_selectedAnchors(self) -> Tuple[BaseAnchor, ...]: - selected = tuple(normalizers.normalizeAnchor(anchor) - for anchor in self._get_selectedAnchors()) + selected = tuple( + normalizers.normalizeAnchor(anchor) + for anchor in self._get_selectedAnchors() + ) return selected def _get_selectedAnchors(self) -> Tuple[BaseAnchor, ...]: @@ -3814,8 +3869,9 @@ def _get_selectedAnchors(self) -> Tuple[BaseAnchor, ...]: """ return self._getSelectedSubObjects(self.anchors) - def _set_base_selectedAnchors(self, - value: CollectionType[Union[int, BaseAnchor]]) -> None: + def _set_base_selectedAnchors( + self, value: CollectionType[Union[int, BaseAnchor]] + ) -> None: normalized = [] for i in value: if isinstance(i, int): @@ -3825,8 +3881,9 @@ def _set_base_selectedAnchors(self, normalized.append(i) self._set_selectedAnchors(normalized) - def _set_selectedAnchors(self, - value: CollectionType[Union[int, BaseAnchor]]) -> None: + def _set_selectedAnchors( + self, value: CollectionType[Union[int, BaseAnchor]] + ) -> None: """Set the selected anchors in the glyph. This is the environment implementation of @@ -3867,12 +3924,14 @@ def _set_selectedAnchors(self, >>> glyph.selectedGuidelines = [0, 2] - """ + """, ) def _get_base_selectedGuidelines(self) -> Tuple[BaseGuideline, ...]: - selected = tuple(normalizers.normalizeGuideline(guideline) - for guideline in self._get_selectedGuidelines()) + selected = tuple( + normalizers.normalizeGuideline(guideline) + for guideline in self._get_selectedGuidelines() + ) return selected def _get_selectedGuidelines(self) -> Tuple[BaseGuideline, ...]: @@ -3892,8 +3951,9 @@ def _get_selectedGuidelines(self) -> Tuple[BaseGuideline, ...]: """ return self._getSelectedSubObjects(self.guidelines) - def _set_base_selectedGuidelines(self, - value: CollectionType[Union[int, BaseGuideline]]) -> None: + def _set_base_selectedGuidelines( + self, value: CollectionType[Union[int, BaseGuideline]] + ) -> None: normalized = [] for i in value: if isinstance(i, int): @@ -3903,8 +3963,9 @@ def _set_base_selectedGuidelines(self, normalized.append(i) self._set_selectedGuidelines(normalized) - def _set_selectedGuidelines(self, - value: CollectionType[Union[int, BaseGuideline]]) -> None: + def _set_selectedGuidelines( + self, value: CollectionType[Union[int, BaseGuideline]] + ) -> None: """Set the selected guidelines in the glyph. This is the environment implementation of diff --git a/Lib/fontParts/base/groups.py b/Lib/fontParts/base/groups.py index b6df3e2d..04cc7271 100644 --- a/Lib/fontParts/base/groups.py +++ b/Lib/fontParts/base/groups.py @@ -4,7 +4,6 @@ class BaseGroups(BaseDict, DeprecatedGroups, RemovedGroups): - """ A Groups object. This object normally created as part of a :class:`BaseFont`. An orphan Groups object can be created like this:: @@ -68,8 +67,9 @@ def findGlyph(self, glyphName): """ glyphName = normalizers.normalizeGlyphName(glyphName) groupNames = self._findGlyph(glyphName) - groupNames = [self.keyNormalizer.__func__( - groupName) for groupName in groupNames] + groupNames = [ + self.keyNormalizer.__func__(groupName) for groupName in groupNames + ] return groupNames def _findGlyph(self, glyphName): @@ -101,7 +101,7 @@ def _findGlyph(self, glyphName): The value will be a :ref:`dict` with :ref:`string` keys representing group names and :ref:`tuple` contaning glyph names. - """ + """, ) def _get_base_side1KerningGroups(self): @@ -134,7 +134,7 @@ def _get_side1KerningGroups(self): The value will be a :ref:`dict` with :ref:`string` keys representing group names and :ref:`tuple` contaning glyph names. - """ + """, ) def _get_base_side2KerningGroups(self): diff --git a/Lib/fontParts/base/guideline.py b/Lib/fontParts/base/guideline.py index 384b736d..2446c538 100644 --- a/Lib/fontParts/base/guideline.py +++ b/Lib/fontParts/base/guideline.py @@ -8,7 +8,7 @@ PointPositionMixin, IdentifierMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.compatibility import GuidelineCompatibilityReporter @@ -17,16 +17,15 @@ class BaseGuideline( - BaseObject, - TransformationMixin, - DeprecatedGuideline, - RemovedGuideline, - PointPositionMixin, - InterpolationMixin, - IdentifierMixin, - SelectionMixin - ): - + BaseObject, + TransformationMixin, + DeprecatedGuideline, + RemovedGuideline, + PointPositionMixin, + InterpolationMixin, + IdentifierMixin, + SelectionMixin, +): """ A guideline object. This object is almost always created with :meth:`BaseGlyph.appendGuideline`. @@ -35,13 +34,7 @@ class BaseGuideline( >>> guideline = RGuideline() """ - copyAttributes = ( - "x", - "y", - "angle", - "name", - "color" - ) + copyAttributes = ("x", "y", "angle", "name", "color") def _reprContents(self): contents = [] @@ -121,7 +114,7 @@ def _set_font(self, font): >>> guideline.x 100 >>> guideline.x = 101 - """ + """, ) def _get_base_x(self): @@ -169,7 +162,7 @@ def _set_x(self, value): >>> guideline.y 100 >>> guideline.y = 101 - """ + """, ) def _get_base_y(self): @@ -223,7 +216,7 @@ def _set_y(self, value): >>> guideline.angle 45.0 >>> guideline.angle = 90 - """ + """, ) def _get_base_angle(self): @@ -288,7 +281,7 @@ def _set_angle(self, value): >>> guideline.index 0 - """ + """, ) def _get_base_index(self): @@ -323,7 +316,7 @@ def _get_index(self): >>> guideline.name 'my guideline' >>> guideline.name = None - """ + """, ) def _get_base_name(self): @@ -372,7 +365,7 @@ def _set_name(self, value): >>> guideline.color None >>> guideline.color = (1, 0, 0, 0.5) - """ + """, ) def _get_base_color(self): diff --git a/Lib/fontParts/base/image.py b/Lib/fontParts/base/image.py index 44315ca8..fd12e40a 100644 --- a/Lib/fontParts/base/image.py +++ b/Lib/fontParts/base/image.py @@ -5,7 +5,7 @@ PointPositionMixin, SelectionMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.color import Color @@ -13,19 +13,14 @@ class BaseImage( - BaseObject, - TransformationMixin, - PointPositionMixin, - SelectionMixin, - DeprecatedImage, - RemovedImage - ): - - copyAttributes = ( - "transformation", - "color", - "data" - ) + BaseObject, + TransformationMixin, + PointPositionMixin, + SelectionMixin, + DeprecatedImage, + RemovedImage, +): + copyAttributes = ("transformation", "color", "data") def _reprContents(self): contents = [ @@ -104,7 +99,7 @@ def _get_font(self): >>> image.transformation (1, 0, 0, 1, 0, 0) >>> image.transformation = (2, 0, 0, 2, 100, -50) - """ + """, ) def _get_base_transformation(self): @@ -139,7 +134,7 @@ def _set_transformation(self, value): >>> image.offset (0, 0) >>> image.offset = (100, -50) - """ + """, ) def _get_base_offset(self): @@ -177,7 +172,7 @@ def _set_offset(self, value): >>> image.scale (1, 1) >>> image.scale = (2, 2) - """ + """, ) def _get_base_scale(self): @@ -215,7 +210,7 @@ def _set_scale(self, value): >>> image.color None >>> image.color = (1, 0, 0, 0.5) - """ + """, ) def _get_base_color(self): @@ -253,7 +248,7 @@ def _set_color(self, value): """ The image's raw byte data. The possible formats are defined by each environment. - """ + """, ) def _get_base_data(self): diff --git a/Lib/fontParts/base/info.py b/Lib/fontParts/base/info.py index 2918d9b4..19013c11 100644 --- a/Lib/fontParts/base/info.py +++ b/Lib/fontParts/base/info.py @@ -1,9 +1,4 @@ -from fontParts.base.base import ( - BaseObject, - dynamicProperty, - interpolate, - reference -) +from fontParts.base.base import BaseObject, dynamicProperty, interpolate, reference from fontParts.base import normalizers from fontParts.base.errors import FontPartsError from fontParts.base.deprecated import DeprecatedInfo, RemovedInfo @@ -52,10 +47,10 @@ def _set_font(self, font): @staticmethod def _validateFontInfoAttributeValue(attr, value): from fontTools.ufoLib import validateFontInfoVersion3ValueForAttribute + valid = validateFontInfoVersion3ValueForAttribute(attr, value) if not valid: - raise ValueError("Invalid value %s for attribute '%s'." - % (value, attr)) + raise ValueError("Invalid value %s for attribute '%s'." % (value, attr)) return value # ---------- @@ -66,6 +61,7 @@ def _validateFontInfoAttributeValue(attr, value): def __hasattr__(self, attr): from fontTools.ufoLib import fontInfoAttributesVersion3 + if attr in fontInfoAttributesVersion3: return True return super(BaseInfo, self).__hasattr__(attr) @@ -74,6 +70,7 @@ def __hasattr__(self, attr): def __getattribute__(self, attr): from fontTools.ufoLib import fontInfoAttributesVersion3 + if attr != "guidelines" and attr in fontInfoAttributesVersion3: value = self._getAttr(attr) if value is not None: @@ -100,6 +97,7 @@ def _getAttr(self, attr): def __setattr__(self, attr, value): from fontTools.ufoLib import fontInfoAttributesVersion3 + if attr != "guidelines" and attr in fontInfoAttributesVersion3: if value is not None: value = self._validateFontInfoAttributeValue(attr, value) @@ -207,6 +205,7 @@ def _update(self, other): Subclasses may override this method. """ from fontTools.ufoLib import fontInfoAttributesVersion3 + for attr in fontInfoAttributesVersion3: if attr == "guidelines": continue @@ -242,6 +241,7 @@ def _toMathInfo(self, guidelines=True): Subclasses may override this method. """ import fontMath + # A little trickery is needed here because MathInfo # handles font level guidelines. Those are not in this # object so we temporarily fake them just enough for @@ -255,7 +255,7 @@ def _toMathInfo(self, guidelines=True): angle=guideline.angle, name=guideline.name, identifier=guideline.identifier, - color=guideline.color + color=guideline.color, ) self.guidelines.append(d) info = fontMath.MathInfo(self) @@ -274,7 +274,7 @@ def _fromMathInfo(self, mathInfo, guidelines=True): position=(guideline["x"], guideline["y"]), angle=guideline["angle"], name=guideline["name"], - color=guideline["color"] + color=guideline["color"], # XXX identifier is lost ) @@ -297,17 +297,26 @@ def interpolate(self, factor, minInfo, maxInfo, round=True, suppressError=True): """ factor = normalizers.normalizeInterpolationFactor(factor) if not isinstance(minInfo, BaseInfo): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") % - (self.__class__.__name__, minInfo.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, minInfo.__class__.__name__) + ) if not isinstance(maxInfo, BaseInfo): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") % - (self.__class__.__name__, maxInfo.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, maxInfo.__class__.__name__) + ) round = normalizers.normalizeBoolean(round) suppressError = normalizers.normalizeBoolean(suppressError) - self._interpolate(factor, minInfo, maxInfo, - round=round, suppressError=suppressError) + self._interpolate( + factor, minInfo, maxInfo, round=round, suppressError=suppressError + ) def _interpolate(self, factor, minInfo, maxInfo, round=True, suppressError=True): """ @@ -321,9 +330,10 @@ def _interpolate(self, factor, minInfo, maxInfo, round=True, suppressError=True) maxInfo = maxInfo._toMathInfo() result = interpolate(minInfo, maxInfo, factor) if result is None and not suppressError: - raise FontPartsError(("Info from font '%s' and font '%s' could not be " - "interpolated.") - % (minInfo.font.name, maxInfo.font.name)) + raise FontPartsError( + ("Info from font '%s' and font '%s' could not be " "interpolated.") + % (minInfo.font.name, maxInfo.font.name) + ) if round: result = result.round() self._fromMathInfo(result) diff --git a/Lib/fontParts/base/kerning.py b/Lib/fontParts/base/kerning.py index 8d0d98cb..c4958930 100644 --- a/Lib/fontParts/base/kerning.py +++ b/Lib/fontParts/base/kerning.py @@ -1,15 +1,9 @@ -from fontParts.base.base import ( - BaseDict, - dynamicProperty, - interpolate, - reference -) +from fontParts.base.base import BaseDict, dynamicProperty, interpolate, reference from fontParts.base import normalizers from fontParts.base.deprecated import DeprecatedKerning, RemovedKerning class BaseKerning(BaseDict, DeprecatedKerning, RemovedKerning): - """ A Kerning object. This object normally created as part of a :class:`BaseFont`. An orphan Kerning object can be created @@ -69,7 +63,7 @@ def scaleBy(self, factor): **factor** will be used to scale the kerning values. >>> myKerning.scaleBy(2) - >>> myKerning.scaleBy((2,3)) + >>> myKerning.scaleBy((2, 3)) """ factor = normalizers.normalizeTransformationScale(factor) self._scale(factor) @@ -98,8 +92,10 @@ def round(self, multiple=1): The default behavior is to round to increments of 1. """ if not isinstance(multiple, int): - raise TypeError("The round multiple must be an int not %s." - % multiple.__class__.__name__) + raise TypeError( + "The round multiple must be an int not %s." + % multiple.__class__.__name__ + ) self._round(multiple) def _round(self, multiple=1): @@ -110,15 +106,19 @@ def _round(self, multiple=1): Subclasses may override this method. """ for pair, value in self.items(): - value = int(normalizers.normalizeVisualRounding( - value / float(multiple))) * multiple + value = ( + int(normalizers.normalizeVisualRounding(value / float(multiple))) + * multiple + ) self[pair] = value # ------------- # Interpolation # ------------- - def interpolate(self, factor, minKerning, maxKerning, round=True, suppressError=True): + def interpolate( + self, factor, minKerning, maxKerning, round=True, suppressError=True + ): """ Interpolates all pairs between two :class:`BaseKerning` objects: @@ -142,20 +142,30 @@ def interpolate(self, factor, minKerning, maxKerning, round=True, suppressError= """ factor = normalizers.normalizeInterpolationFactor(factor) if not isinstance(minKerning, BaseKerning): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") % ( - self.__class__.__name__, minKerning.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, minKerning.__class__.__name__) + ) if not isinstance(maxKerning, BaseKerning): - raise TypeError(("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") % ( - self.__class__.__name__, maxKerning.__class__.__name__)) + raise TypeError( + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) + % (self.__class__.__name__, maxKerning.__class__.__name__) + ) round = normalizers.normalizeBoolean(round) suppressError = normalizers.normalizeBoolean(suppressError) - self._interpolate(factor, minKerning, maxKerning, - round=round, suppressError=suppressError) + self._interpolate( + factor, minKerning, maxKerning, round=round, suppressError=suppressError + ) - def _interpolate(self, factor, minKerning, maxKerning, - round=True, suppressError=True): + def _interpolate( + self, factor, minKerning, maxKerning, round=True, suppressError=True + ): """ This is the environment implementation of :meth:`BaseKerning.interpolate`. @@ -174,17 +184,17 @@ def _interpolate(self, factor, minKerning, maxKerning, setRoundIntegerFunction(normalizers.normalizeVisualRounding) kerningGroupCompatibility = self._testKerningGroupCompatibility( - minKerning, - maxKerning, - suppressError=suppressError - ) + minKerning, maxKerning, suppressError=suppressError + ) if not kerningGroupCompatibility: self.clear() else: minKerning = fontMath.MathKerning( - kerning=minKerning, groups=minKerning.font.groups) + kerning=minKerning, groups=minKerning.font.groups + ) maxKerning = fontMath.MathKerning( - kerning=maxKerning, groups=maxKerning.font.groups) + kerning=maxKerning, groups=maxKerning.font.groups + ) result = interpolate(minKerning, maxKerning, factor) if round: result.round() @@ -198,9 +208,9 @@ def _testKerningGroupCompatibility(minKerning, maxKerning, suppressError=False): match = True while match: for _, sideAttr in ( - ("side 1", "side1KerningGroups"), - ("side 2", "side2KerningGroups") - ): + ("side 1", "side1KerningGroups"), + ("side 2", "side2KerningGroups"), + ): minSideGroups = getattr(minGroups, sideAttr) maxSideGroups = getattr(maxGroups, sideAttr) if minSideGroups.keys() != maxSideGroups.keys(): @@ -374,6 +384,7 @@ def _find(self, pair, default=None): :ref:`type-int-float` or `default`. """ from fontTools.ufoLib.kerning import lookupKerningValue + font = self.font groups = font.groups return lookupKerningValue(pair, self, groups, fallback=default) diff --git a/Lib/fontParts/base/layer.py b/Lib/fontParts/base/layer.py index 568be5d2..050be2d5 100644 --- a/Lib/fontParts/base/layer.py +++ b/Lib/fontParts/base/layer.py @@ -8,7 +8,7 @@ InterpolationMixin, SelectionMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.compatibility import LayerCompatibilityReporter @@ -19,8 +19,9 @@ CollectionType, ColorType, FactorType, - ReverseComponentMappingType + ReverseComponentMappingType, ) + if TYPE_CHECKING: from fontParts.base.font import BaseFont from fontParts.base.glyph import BaseGlyph @@ -396,10 +397,7 @@ def insertGlyph(self, glyph: BaseGlyph, name: Optional[str] = None) -> None: name = glyph.name self[name] = glyph - def _insertGlyph(self, - glyph: BaseGlyph, - name: str, - **kwargs: Any) -> BaseGlyph: + def _insertGlyph(self, glyph: BaseGlyph, name: str, **kwargs: Any) -> BaseGlyph: r"""Insert a specified glyph into the native layer. This is the environment implementation of @@ -452,12 +450,13 @@ def _insertGlyph(self, >>> layer.selectedGlyphs = someGlyphs - """ + """, ) def _get_base_selectedGlyphs(self) -> Tuple[BaseGlyph, ...]: - selected = tuple(normalizers.normalizeGlyph(glyph) - for glyph in self._get_selectedGlyphs()) + selected = tuple( + normalizers.normalizeGlyph(glyph) for glyph in self._get_selectedGlyphs() + ) return selected def _get_selectedGlyphs(self) -> Tuple[BaseGlyph]: @@ -517,12 +516,14 @@ def _set_selectedGlyphs(self, value: CollectionType[BaseGlyph]) -> None: >>> layer.selectedGlyphNames = ["A", "B", "C"] - """ + """, ) def _get_base_selectedGlyphNames(self) -> Tuple[str, ...]: - selected = tuple(normalizers.normalizeGlyphName(name) - for name in self._get_selectedGlyphNames()) + selected = tuple( + normalizers.normalizeGlyphName(name) + for name in self._get_selectedGlyphNames() + ) return selected def _get_selectedGlyphNames(self) -> Tuple[str, ...]: @@ -572,10 +573,7 @@ def _set_selectedGlyphNames(self, value: CollectionType[str]) -> None: has_key: Callable[[_BaseGlyphVendor, str], bool] = __contains__ -class BaseLayer(_BaseGlyphVendor, - InterpolationMixin, - DeprecatedLayer, - RemovedLayer): +class BaseLayer(_BaseGlyphVendor, InterpolationMixin, DeprecatedLayer, RemovedLayer): """Represent the basis for a layer object. This object will almost always be created by retrieving it from a @@ -596,11 +594,7 @@ def _reprContents(self) -> List[str]: # Copy # ---- - copyAttributes: Tuple[str, ...] = ( - "name", - "color", - "lib" - ) + copyAttributes: Tuple[str, ...] = ("name", "color", "lib") def copy(self) -> BaseLayer: """Copy data from the current layer into a new layer. @@ -664,7 +658,7 @@ def copyData(self, source: BaseLayer) -> None: >>> font = layer.font - """ + """, ) def _get_font(self) -> Optional[BaseFont]: @@ -702,7 +696,7 @@ def _set_font(self, font: Optional[BaseFont]) -> None: "foreground" >>> layer.name = "top" - """ + """, ) def _get_base_name(self) -> Optional[str]: @@ -719,9 +713,7 @@ def _set_base_name(self, value: str) -> None: if font is not None: existing = self.font.layerOrder if value in existing: - raise ValueError( - "A layer with the name '%s' already exists." % value - ) + raise ValueError("A layer with the name '%s' already exists." % value) self._set_name(value) def _get_name(self) -> Optional[str]: # type: ignore[return] @@ -785,7 +777,7 @@ def _set_name(self, value: str, **kwargs: Any) -> None: None >>> layer.color = (1, 0, 0, 0.5) - """ + """, ) def _get_base_color(self) -> ColorType: @@ -858,7 +850,7 @@ def _set_color(self, value: ColorType, **kwargs: Any) -> None: >>> layer.lib["org.robofab.hello"] "world" - """ + """, ) def _get_base_lib(self) -> BaseLib: @@ -900,7 +892,7 @@ def _get_lib(self) -> BaseLib: # type: ignore[return] >>> layer.tempLib["org.robofab.hello"] "world" - """ + """, ) def _get_base_tempLib(self) -> BaseLib: @@ -985,12 +977,14 @@ def _autoUnicodes(self) -> None: # Interpolation # ------------- - def interpolate(self, - factor: FactorType, - minLayer: BaseLayer, - maxLayer: BaseLayer, - round: bool = True, - suppressError: bool = True) -> None: + def interpolate( + self, + factor: FactorType, + minLayer: BaseLayer, + maxLayer: BaseLayer, + round: bool = True, + suppressError: bool = True, + ) -> None: """Interpolate all possible data in the layer. The interpolation occurs on a 0 to 1.0 range between `minLayer` @@ -1020,27 +1014,34 @@ def interpolate(self, factor = normalizers.normalizeInterpolationFactor(factor) if not isinstance(minLayer, BaseLayer): raise TypeError( - ("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) % (self.__class__.__name__, minLayer.__class__.__name__) ) if not isinstance(maxLayer, BaseLayer): raise TypeError( - ("Interpolation to an instance of %r can not be " - "performed from an instance of %r.") + ( + "Interpolation to an instance of %r can not be " + "performed from an instance of %r." + ) % (self.__class__.__name__, maxLayer.__class__.__name__) ) round = normalizers.normalizeBoolean(round) suppressError = normalizers.normalizeBoolean(suppressError) - self._interpolate(factor, minLayer, maxLayer, - round=round, suppressError=suppressError) - - def _interpolate(self, - factor: FactorType, - minLayer: BaseLayer, - maxLayer: BaseLayer, - round: bool, - suppressError: bool) -> None: + self._interpolate( + factor, minLayer, maxLayer, round=round, suppressError=suppressError + ) + + def _interpolate( + self, + factor: FactorType, + minLayer: BaseLayer, + maxLayer: BaseLayer, + round: bool, + suppressError: bool, + ) -> None: """Interpolate all possible data in the native layer. This is the environment implementation of :meth:`BaseLayer.interpolate`. @@ -1073,8 +1074,9 @@ def _interpolate(self, minGlyph = minLayer[glyphName] maxGlyph = maxLayer[glyphName] dstGlyph = self.newGlyph(glyphName) - dstGlyph.interpolate(factor, minGlyph, maxGlyph, - round=round, suppressError=suppressError) + dstGlyph.interpolate( + factor, minGlyph, maxGlyph, round=round, suppressError=suppressError + ) compatibilityReporterClass = LayerCompatibilityReporter @@ -1100,9 +1102,9 @@ def isCompatible(self, other: BaseLayer) -> tuple[bool, str]: """ return super(BaseLayer, self).isCompatible(other, BaseLayer) - def _isCompatible(self, - other: BaseLib, - reporter: LayerCompatibilityReporter) -> None: + def _isCompatible( + self, other: BaseLib, reporter: LayerCompatibilityReporter + ) -> None: """Evaluate interpolation compatibility with another native layer. This is the environment implementation of :meth:`BaseFont.isCompatible`. diff --git a/Lib/fontParts/base/lib.py b/Lib/fontParts/base/lib.py index ec37c6ab..eda0e020 100644 --- a/Lib/fontParts/base/lib.py +++ b/Lib/fontParts/base/lib.py @@ -4,7 +4,6 @@ class BaseLib(BaseDict, DeprecatedLib, RemovedLib): - """ A Lib object. This object normally created as part of a :class:`BaseFont`. An orphan Lib object can be created like this:: diff --git a/Lib/fontParts/base/normalizers.py b/Lib/fontParts/base/normalizers.py index b3cce30c..b06043fe 100644 --- a/Lib/fontParts/base/normalizers.py +++ b/Lib/fontParts/base/normalizers.py @@ -43,8 +43,10 @@ def normalizeFileFormatVersion(value: int) -> int: """ if not isinstance(value, int): - raise TypeError("Expected file formmat verison 'value' to be of type int, not %s." - % type(value).__name__) + raise TypeError( + "Expected file formmat verison 'value' to be of type int, not %s." + % type(value).__name__ + ) return value @@ -58,8 +60,10 @@ def normalizeFileStructure(value: str) -> str: """ allowedFileStructures = ["zip", "package"] if value not in allowedFileStructures: - raise TypeError("File Structure must be %s, not %s" - % (", ".join(allowedFileStructures), value)) + raise TypeError( + "File Structure must be %s, not %s" + % (", ".join(allowedFileStructures), value) + ) return value @@ -84,19 +88,21 @@ def normalizeLayerOrder(value: CollectionType[str], font) -> Tuple[str, ...]: """ if not isinstance(value, (tuple, list)): - raise TypeError("Layer order must be a list, not %s." - % type(value).__name__) + raise TypeError("Layer order must be a list, not %s." % type(value).__name__) for v in value: normalizeLayerName(v) fontLayers = [layer.name for layer in font.layers] for name in value: if name not in fontLayers: - raise ValueError("Layer must exist in font. %s does not exist " - "in font.layers." % name) + raise ValueError( + "Layer must exist in font. %s does not exist " "in font.layers." % name + ) duplicates = [v for v, count in Counter(value).items() if count > 1] if len(duplicates) != 0: - raise ValueError("Duplicate layers are not allowed. Layer name(s) " - "'%s' are duplicate(s)." % ", ".join(duplicates)) + raise ValueError( + "Duplicate layers are not allowed. Layer name(s) " + "'%s' are duplicate(s)." % ", ".join(duplicates) + ) return tuple(value) @@ -138,14 +144,15 @@ def normalizeGlyphOrder(value: CollectionType[str]) -> Tuple[str, ...]: """ if not isinstance(value, (tuple, list)): - raise TypeError("Glyph order must be a list, not %s." - % type(value).__name__) + raise TypeError("Glyph order must be a list, not %s." % type(value).__name__) for v in value: normalizeGlyphName(v) duplicates = sorted(v for v, count in Counter(value).items() if count > 1) if len(duplicates) != 0: - raise ValueError("Duplicate glyph names are not allowed. Glyph " - "name(s) '%s' are duplicate." % ", ".join(duplicates)) + raise ValueError( + "Duplicate glyph names are not allowed. Glyph " + "name(s) '%s' are duplicate." % ", ".join(duplicates) + ) return tuple(value) @@ -153,6 +160,7 @@ def normalizeGlyphOrder(value: CollectionType[str]) -> Tuple[str, ...]: # Kerning # ------- + def normalizeKerningKey(value: PairCollectionType[str]) -> PairType[str]: """Normalize a kerning key. @@ -175,25 +183,24 @@ def normalizeKerningKey(value: PairCollectionType[str]) -> PairType[str]: """ if not isinstance(value, (tuple, list)): - raise TypeError("Kerning key must be a tuple instance, not %s." - % type(value).__name__) + raise TypeError( + "Kerning key must be a tuple instance, not %s." % type(value).__name__ + ) if len(value) != 2: - raise ValueError("Kerning key must be a tuple containing two items, " - "not %d." % len(value)) + raise ValueError( + "Kerning key must be a tuple containing two items, " "not %d." % len(value) + ) for v in value: if not isinstance(v, str): - raise TypeError("Kerning key items must be strings, not %s." - % type(v).__name__) + raise TypeError( + "Kerning key items must be strings, not %s." % type(v).__name__ + ) if len(v) < 1: raise ValueError("Kerning key items must be at least one character long") - if value[0].startswith("public.") and not value[0].startswith( - "public.kern1."): - raise ValueError("Left Kerning key group must start with " - "public.kern1.") - if value[1].startswith("public.") and not value[1].startswith( - "public.kern2."): - raise ValueError("Right Kerning key group must start with " - "public.kern2.") + if value[0].startswith("public.") and not value[0].startswith("public.kern1."): + raise ValueError("Left Kerning key group must start with " "public.kern1.") + if value[1].startswith("public.") and not value[1].startswith("public.kern2."): + raise ValueError("Right Kerning key group must start with " "public.kern2.") return tuple(value) @@ -207,10 +214,12 @@ def normalizeKerningValue(value: IntFloatType) -> IntFloatType: """ if not isinstance(value, (int, float)): - raise TypeError("Kerning value must be a int or a float, not %s." - % type(value).__name__) + raise TypeError( + "Kerning value must be a int or a float, not %s." % type(value).__name__ + ) return value + # ------ # Groups # ------ @@ -226,8 +235,7 @@ def normalizeGroupKey(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Group key must be a string, not %s." - % type(value).__name__) + raise TypeError("Group key must be a string, not %s." % type(value).__name__) if len(value) < 1: raise ValueError("Group key must be at least one character long.") return value @@ -246,8 +254,7 @@ def normalizeGroupValue(value: CollectionType[str]) -> Tuple[str, ...]: """ if not isinstance(value, (tuple, list)): - raise TypeError("Group value must be a list, not %s." - % type(value).__name__) + raise TypeError("Group value must be a list, not %s." % type(value).__name__) value = [normalizeGlyphName(v) for v in value] return tuple(value) @@ -256,6 +263,7 @@ def normalizeGroupValue(value: CollectionType[str]) -> Tuple[str, ...]: # Features # -------- + def normalizeFeatureText(value: str) -> str: """Normalize feature text. @@ -265,8 +273,7 @@ def normalizeFeatureText(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Feature text must be a string, not %s." - % type(value).__name__) + raise TypeError("Feature text must be a string, not %s." % type(value).__name__) return value @@ -274,6 +281,7 @@ def normalizeFeatureText(value: str) -> str: # Lib # --- + def normalizeLibKey(value: str) -> str: """Normalize a lib key. @@ -284,8 +292,7 @@ def normalizeLibKey(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Lib key must be a string, not %s." - % type(value).__name__) + raise TypeError("Lib key must be a string, not %s." % type(value).__name__) if len(value) < 1: raise ValueError("Lib key must be at least one character.") return value @@ -319,6 +326,7 @@ def normalizeLibValue(value: Any) -> Any: # Layer # ----- + def normalizeLayer(value: BaseLayer) -> BaseLayer: """Normalize a layer. @@ -328,6 +336,7 @@ def normalizeLayer(value: BaseLayer) -> BaseLayer: """ from fontParts.base.layer import BaseLayer + return normalizeInternalObjectType(value, BaseLayer, "Layer") @@ -341,8 +350,7 @@ def normalizeLayerName(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Layer names must be strings, not %s." - % type(value).__name__) + raise TypeError("Layer names must be strings, not %s." % type(value).__name__) if len(value) < 1: raise ValueError("Layer names must be at least one character long.") return value @@ -352,6 +360,7 @@ def normalizeLayerName(value: str) -> str: # Glyph # ----- + def normalizeGlyph(value: BaseGlyph) -> BaseGlyph: """Normalize a glyph. @@ -361,6 +370,7 @@ def normalizeGlyph(value: BaseGlyph) -> BaseGlyph: """ from fontParts.base.glyph import BaseGlyph + return normalizeInternalObjectType(value, BaseGlyph, "Glyph") @@ -397,8 +407,7 @@ def normalizeGlyphUnicodes(value: CollectionType[int]) -> Tuple[int, ...]: """ if not isinstance(value, (tuple, list)): - raise TypeError("Glyph unicodes must be a list, not %s." - % type(value).__name__) + raise TypeError("Glyph unicodes must be a list, not %s." % type(value).__name__) values = [normalizeGlyphUnicode(v) for v in value] duplicates = [v for v, count in Counter(value).items() if count > 1] if len(duplicates) != 0: @@ -419,8 +428,9 @@ def normalizeGlyphUnicode(value: Union[int, str]) -> int: """ if not isinstance(value, (int, str)) or isinstance(value, bool): - raise TypeError("Glyph unicode must be an int or hex string, not %s." - % type(value).__name__) + raise TypeError( + "Glyph unicode must be an int or hex string, not %s." % type(value).__name__ + ) if isinstance(value, str): try: value = int(value, 16) @@ -440,8 +450,10 @@ def normalizeGlyphWidth(value: IntFloatType) -> IntFloatType: """ if not isinstance(value, (int, float)): - raise TypeError("Glyph width must be an :ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Glyph width must be an :ref:`type-int-float`, not %s." + % type(value).__name__ + ) return value @@ -455,8 +467,10 @@ def normalizeGlyphLeftMargin(value: Optional[IntFloatType]) -> Optional[IntFloat """ if not isinstance(value, (int, float)) and value is not None: - raise TypeError("Glyph left margin must be an :ref:`type-int-float`, " - "not %s." % type(value).__name__) + raise TypeError( + "Glyph left margin must be an :ref:`type-int-float`, " + "not %s." % type(value).__name__ + ) return value @@ -470,8 +484,10 @@ def normalizeGlyphRightMargin(value: Optional[IntFloatType]) -> Optional[IntFloa """ if not isinstance(value, (int, float)) and value is not None: - raise TypeError("Glyph right margin must be an :ref:`type-int-float`, " - "not %s." % type(value).__name__) + raise TypeError( + "Glyph right margin must be an :ref:`type-int-float`, " + "not %s." % type(value).__name__ + ) return value @@ -484,8 +500,10 @@ def normalizeGlyphHeight(value: IntFloatType) -> IntFloatType: """ if not isinstance(value, (int, float)): - raise TypeError("Glyph height must be an :ref:`type-int-float`, not " - "%s." % type(value).__name__) + raise TypeError( + "Glyph height must be an :ref:`type-int-float`, not " + "%s." % type(value).__name__ + ) return value @@ -499,9 +517,10 @@ def normalizeGlyphBottomMargin(value: Optional[IntFloatType]) -> Optional[IntFlo """ if not isinstance(value, (int, float)) and value is not None: - raise TypeError("Glyph bottom margin must be an " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Glyph bottom margin must be an " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) return value @@ -515,9 +534,10 @@ def normalizeGlyphTopMargin(value: Optional[IntFloatType]) -> Optional[IntFloatT """ if not isinstance(value, (int, float)) and value is not None: - raise TypeError("Glyph top margin must be an " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Glyph top margin must be an " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) return value @@ -532,15 +552,16 @@ def normalizeGlyphFormatVersion(value: IntFloatType) -> int: """ if not isinstance(value, (int, float)): - raise TypeError("Glyph Format Version must be an " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Glyph Format Version must be an " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) value = int(value) if value not in (1, 2): - raise ValueError("Glyph Format Version must be either 1 or 2, not %s." - % value) + raise ValueError("Glyph Format Version must be either 1 or 2, not %s." % value) return value + # ------- # Contour # ------- @@ -555,6 +576,7 @@ def normalizeContour(value: BaseContour) -> BaseContour: """ from fontParts.base.contour import BaseContour + return normalizeInternalObjectType(value, BaseContour, "Contour") @@ -562,6 +584,7 @@ def normalizeContour(value: BaseContour) -> BaseContour: # Point # ----- + def normalizePointType(value: str) -> str: """Normalize a point type. @@ -583,13 +606,13 @@ def normalizePointType(value: str) -> str: :raises ValueError: If `value` is not one of the allowed types. """ - allowedTypes = ['move', 'line', 'offcurve', 'curve', 'qcurve'] + allowedTypes = ["move", "line", "offcurve", "curve", "qcurve"] if not isinstance(value, str): - raise TypeError("Point type must be a string, not %s." - % type(value).__name__) + raise TypeError("Point type must be a string, not %s." % type(value).__name__) if value not in allowedTypes: - raise ValueError("Point type must be '%s'; not %r." - % ("', '".join(allowedTypes), value)) + raise ValueError( + "Point type must be '%s'; not %r." % ("', '".join(allowedTypes), value) + ) return value @@ -603,8 +626,7 @@ def normalizePointName(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Point names must be strings, not %s." - % type(value).__name__) + raise TypeError("Point names must be strings, not %s." % type(value).__name__) if len(value) < 1: raise ValueError("Point names must be at least one character long.") return value @@ -619,8 +641,10 @@ def normalizePoint(value: BasePoint) -> BasePoint: """ from fontParts.base.point import BasePoint + return normalizeInternalObjectType(value, BasePoint, "Point") + # ------- # Segment # ------- @@ -635,6 +659,7 @@ def normalizeSegment(value: BaseSegment) -> BaseSegment: """ from fontParts.base.segment import BaseSegment + return normalizeInternalObjectType(value, BaseSegment, "Segment") @@ -658,13 +683,13 @@ def normalizeSegmentType(value: str) -> str: :raises ValueError: If `value` is not one of the allowed types. """ - allowedTypes = ['move', 'line', 'curve', 'qcurve'] + allowedTypes = ["move", "line", "curve", "qcurve"] if not isinstance(value, str): - raise TypeError("Segment type must be a string, not %s." - % type(value).__name__) + raise TypeError("Segment type must be a string, not %s." % type(value).__name__) if value not in allowedTypes: - raise ValueError("Segment type must be '%s'; not %r." - % ("', '".join(allowedTypes), value)) + raise ValueError( + "Segment type must be '%s'; not %r." % ("', '".join(allowedTypes), value) + ) return value @@ -672,6 +697,7 @@ def normalizeSegmentType(value: str) -> str: # BPoint # ------ + def normalizeBPoint(value: BaseBPoint) -> BaseBPoint: """Normalize a bPoint. @@ -681,6 +707,7 @@ def normalizeBPoint(value: BaseBPoint) -> BaseBPoint: """ from fontParts.base.bPoint import BaseBPoint + return normalizeInternalObjectType(value, BaseBPoint, "bPoint") @@ -702,13 +729,11 @@ def normalizeBPointType(value: str) -> str: :raises ValueError: If `value` is not one of the allowed types. """ - allowedTypes = ['corner', 'curve'] + allowedTypes = ["corner", "curve"] if not isinstance(value, str): - raise TypeError("bPoint type must be a string, not %s." - % type(value).__name__) + raise TypeError("bPoint type must be a string, not %s." % type(value).__name__) if value not in allowedTypes: - raise ValueError("bPoint type must be 'corner' or 'curve', not %r." - % value) + raise ValueError("bPoint type must be 'corner' or 'curve', not %r." % value) return value @@ -716,6 +741,7 @@ def normalizeBPointType(value: str) -> str: # Component # --------- + def normalizeComponent(value: BaseComponent) -> BaseComponent: """Normalize a component. @@ -725,6 +751,7 @@ def normalizeComponent(value: BaseComponent) -> BaseComponent: """ from fontParts.base.component import BaseComponent + return normalizeInternalObjectType(value, BaseComponent, "Component") @@ -738,17 +765,22 @@ def normalizeComponentScale(value: PairCollectionType[IntFloatType]) -> PairType """ if not isinstance(value, (list, tuple)): - raise TypeError("Component scale must be a tuple " - "instance, not %s." % type(value).__name__) + raise TypeError( + "Component scale must be a tuple " + "instance, not %s." % type(value).__name__ + ) else: if not len(value) == 2: - raise ValueError("Transformation scale tuple must contain two " - "values, not %d." % len(value)) + raise ValueError( + "Transformation scale tuple must contain two " + "values, not %d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Transformation scale tuple values must be an " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Transformation scale tuple values must be an " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) value = tuple(float(v) for v in value) return value @@ -757,6 +789,7 @@ def normalizeComponentScale(value: PairCollectionType[IntFloatType]) -> PairType # Anchor # ------ + def normalizeAnchor(value: BaseAnchor) -> BaseAnchor: """Normalize an anchor. @@ -766,6 +799,7 @@ def normalizeAnchor(value: BaseAnchor) -> BaseAnchor: """ from fontParts.base.anchor import BaseAnchor + return normalizeInternalObjectType(value, BaseAnchor, "Anchor") @@ -782,11 +816,11 @@ def normalizeAnchorName(value: str) -> str: if value is None: return None if not isinstance(value, str): - raise TypeError("Anchor names must be strings, not %s." - % type(value).__name__) + raise TypeError("Anchor names must be strings, not %s." % type(value).__name__) if len(value) < 1: - raise ValueError(("Anchor names must be at least one character " - "long or None.")) + raise ValueError( + ("Anchor names must be at least one character " "long or None.") + ) return value @@ -794,6 +828,7 @@ def normalizeAnchorName(value: str) -> str: # Guideline # --------- + def normalizeGuideline(value: BaseGuideline) -> BaseGuideline: """Normalize a guideline. @@ -803,6 +838,7 @@ def normalizeGuideline(value: BaseGuideline) -> BaseGuideline: """ from fontParts.base.guideline import BaseGuideline + return normalizeInternalObjectType(value, BaseGuideline, "Guideline") @@ -816,11 +852,11 @@ def normalizeGuidelineName(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Guideline names must be strings, not %s." - % type(value).__name__) + raise TypeError( + "Guideline names must be strings, not %s." % type(value).__name__ + ) if len(value) < 1: - raise ValueError("Guideline names must be at least one character " - "long.") + raise ValueError("Guideline names must be at least one character " "long.") return value @@ -828,6 +864,7 @@ def normalizeGuidelineName(value: str) -> str: # Generic # ------- + def normalizeInternalObjectType(value: object, cls: Type[T], name: str) -> T: """Normalize an internal object type. @@ -839,8 +876,9 @@ def normalizeInternalObjectType(value: object, cls: Type[T], name: str) -> T: """ if not isinstance(value, cls): - raise TypeError("%s must be a %s instance, not %s." - % (name, name, type(value).__name__)) + raise TypeError( + "%s must be a %s instance, not %s." % (name, name, type(value).__name__) + ) return value @@ -856,13 +894,13 @@ def normalizeBoolean(value: int) -> bool: if isinstance(value, int) and value in (0, 1): value = bool(value) if not isinstance(value, bool): - raise ValueError("Boolean values must be True or False, not '%s'." - % value) + raise ValueError("Boolean values must be True or False, not '%s'." % value) return value # Identification + def normalizeIndex(value: Optional[int]) -> Optional[int]: """Normalize an index. @@ -873,8 +911,9 @@ def normalizeIndex(value: Optional[int]) -> Optional[int]: """ if value is not None: if not isinstance(value, int): - raise TypeError("Indexes must be None or integers, not %s." - % type(value).__name__) + raise TypeError( + "Indexes must be None or integers, not %s." % type(value).__name__ + ) return value @@ -896,24 +935,27 @@ def normalizeIdentifier(value: Optional[str]) -> Optional[str]: if value is None: return value if not isinstance(value, str): - raise TypeError("Identifiers must be strings, not %s." - % type(value).__name__) + raise TypeError("Identifiers must be strings, not %s." % type(value).__name__) if len(value) == 0: raise ValueError("The identifier string is empty.") if len(value) > 100: - raise ValueError("The identifier string has a length (%d) greater " - "than the maximum allowed (100)." % len(value)) + raise ValueError( + "The identifier string has a length (%d) greater " + "than the maximum allowed (100)." % len(value) + ) for c in value: v = ord(c) if v < 0x20 or v > 0x7E: - raise ValueError("The identifier string ('%s') contains a " - "character outside of the range 0x20 - 0x7E." - % value) + raise ValueError( + "The identifier string ('%s') contains a " + "character outside of the range 0x20 - 0x7E." % value + ) return value # Coordinates + def normalizeX(value: IntFloatType) -> IntFloatType: """Normalize an x-coordinate. @@ -923,9 +965,10 @@ def normalizeX(value: IntFloatType) -> IntFloatType: """ if not isinstance(value, (int, float)): - raise TypeError("X-coordinates must be instances of " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "X-coordinates must be instances of " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) return value @@ -938,14 +981,16 @@ def normalizeY(value: IntFloatType) -> IntFloatType: """ if not isinstance(value, (int, float)): - raise TypeError("Y-coordinates must be instances of " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Y-coordinates must be instances of " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) return value -def normalizeCoordinateTuple(value: PairCollectionType[IntFloatType] - ) -> PairType[IntFloatType]: +def normalizeCoordinateTuple( + value: PairCollectionType[IntFloatType], +) -> PairType[IntFloatType]: """Normalize a coordinate tuple. :param value: The coordinate tuple to noramlize as a :class:`list` @@ -957,19 +1002,22 @@ def normalizeCoordinateTuple(value: PairCollectionType[IntFloatType] """ if not isinstance(value, (tuple, list)): - raise TypeError("Coordinates must be tuple instances, not %s." - % type(value).__name__) + raise TypeError( + "Coordinates must be tuple instances, not %s." % type(value).__name__ + ) if len(value) != 2: - raise ValueError("Coordinates must be tuples containing two items, " - "not %d." % len(value)) + raise ValueError( + "Coordinates must be tuples containing two items, " "not %d." % len(value) + ) x, y = value x = normalizeX(x) y = normalizeY(y) return (x, y) -def normalizeBoundingBox(value: QuadrupleCollectionType[IntFloatType] - ) -> QuadrupleType[float]: +def normalizeBoundingBox( + value: QuadrupleCollectionType[IntFloatType], +) -> QuadrupleType[float]: """Normalize a bounding box. :param value: The bounding box to normalize as a :class:`list` @@ -989,22 +1037,23 @@ def normalizeBoundingBox(value: QuadrupleCollectionType[IntFloatType] """ if not isinstance(value, (tuple, list)): - raise TypeError("Bounding box must be tuple instances, not %s." - % type(value).__name__) + raise TypeError( + "Bounding box must be tuple instances, not %s." % type(value).__name__ + ) if len(value) != 4: - raise ValueError("Bounding box must be tuples containing four items, not " - "%d." % len(value)) + raise ValueError( + "Bounding box must be tuples containing four items, not " "%d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Bounding box values must be instances of " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Bounding box values must be instances of " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) if value[0] > value[2]: - raise ValueError("Bounding box xMin must be less than or equal to " - "xMax.") + raise ValueError("Bounding box xMin must be less than or equal to " "xMax.") if value[1] > value[3]: - raise ValueError("Bounding box yMin must be less than or equal to " - "yMax.") + raise ValueError("Bounding box yMin must be less than or equal to " "yMax.") return tuple(float(v) for v in value) @@ -1018,11 +1067,14 @@ def normalizeArea(value: IntFloatType) -> float: """ if not isinstance(value, (int, float)): - raise TypeError("Area must be an instance of :ref:`type-int-float`, " - "not %s." % type(value).__name__) + raise TypeError( + "Area must be an instance of :ref:`type-int-float`, " + "not %s." % type(value).__name__ + ) if value < 0: - raise ValueError("Area must be a positive :ref:`type-int-float`, " - "not %s." % repr(value)) + raise ValueError( + "Area must be a positive :ref:`type-int-float`, " "not %s." % repr(value) + ) return float(value) @@ -1039,9 +1091,10 @@ def normalizeRotationAngle(value: IntFloatType) -> float: """ if not isinstance(value, (int, float)): - raise TypeError("Angle must be instances of " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Angle must be instances of " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) if abs(value) > 360: raise ValueError("Angle must be between -360 and 360.") if value < 0: @@ -1051,8 +1104,10 @@ def normalizeRotationAngle(value: IntFloatType) -> float: # Color -def normalizeColor(value: QuadrupleCollectionType[IntFloatType] - ) -> QuadrupleType[float]: + +def normalizeColor( + value: QuadrupleCollectionType[IntFloatType], +) -> QuadrupleType[float]: """Normalize a color. :param value: The color to normalize as a :class:`list` or :class:`tuple` @@ -1070,24 +1125,30 @@ def normalizeColor(value: QuadrupleCollectionType[IntFloatType] """ from fontParts.base.color import Color + if not isinstance(value, (tuple, list, Color)): - raise TypeError("Colors must be tuple instances, not %s." - % type(value).__name__) + raise TypeError( + "Colors must be tuple instances, not %s." % type(value).__name__ + ) if not len(value) == 4: - raise ValueError("Colors must contain four values, not %d." - % len(value)) + raise ValueError("Colors must contain four values, not %d." % len(value)) for component, v in zip("rgba", value): if not isinstance(v, (int, float)): - raise TypeError("The value for the %s component (%s) is not " - "an int or float." % (component, v)) + raise TypeError( + "The value for the %s component (%s) is not " + "an int or float." % (component, v) + ) if v < 0 or v > 1: - raise ValueError("The value for the %s component (%s) is not " - "between 0 and 1." % (component, v)) + raise ValueError( + "The value for the %s component (%s) is not " + "between 0 and 1." % (component, v) + ) return tuple(float(v) for v in value) # Note + def normalizeGlyphNote(value: str) -> str: """Normalize a glyph note. @@ -1097,13 +1158,13 @@ def normalizeGlyphNote(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("Note must be a string, not %s." - % type(value).__name__) + raise TypeError("Note must be a string, not %s." % type(value).__name__) return value # File Path + def normalizeFilePath(value: str) -> str: """Normalize a file path. @@ -1113,13 +1174,13 @@ def normalizeFilePath(value: str) -> str: """ if not isinstance(value, str): - raise TypeError("File paths must be strings, not %s." - % type(value).__name__) + raise TypeError("File paths must be strings, not %s." % type(value).__name__) return value # Interpolation + def normalizeInterpolationFactor(value: TransformationType) -> PairType[float]: """Normalize an interpolation factor. @@ -1138,19 +1199,24 @@ def normalizeInterpolationFactor(value: TransformationType) -> PairType[float]: """ if not isinstance(value, (int, float, list, tuple)): - raise TypeError("Interpolation factor must be an int, float, tuple, " - "or list, not %s." % type(value).__name__) + raise TypeError( + "Interpolation factor must be an int, float, tuple, " + "or list, not %s." % type(value).__name__ + ) if isinstance(value, (int, float)): value = (float(value), float(value)) else: if len(value) != 2: - raise ValueError("Interpolation factor tuple must contain two " - "items, not %d." % len(value)) + raise ValueError( + "Interpolation factor tuple must contain two " + "items, not %d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Interpolation factor tuple values must be " - "instances of int or float, not %s." - % type(v).__name__) + raise TypeError( + "Interpolation factor tuple values must be " + "instances of int or float, not %s." % type(v).__name__ + ) value = tuple(float(v) for v in value) return value @@ -1159,8 +1225,10 @@ def normalizeInterpolationFactor(value: TransformationType) -> PairType[float]: # Transformations # --------------- -def normalizeTransformationMatrix(value: SextupleCollectionType[IntFloatType] - ) -> SextupleType[float]: + +def normalizeTransformationMatrix( + value: SextupleCollectionType[IntFloatType], +) -> SextupleType[float]: """Normalize a transformation matrix. :param value: The transformation matrix to normalize as a :class:`list` @@ -1174,21 +1242,26 @@ def normalizeTransformationMatrix(value: SextupleCollectionType[IntFloatType] """ if not isinstance(value, (tuple, list)): - raise TypeError("Transformation matrices must be tuple instances, " - "not %s." % type(value).__name__) + raise TypeError( + "Transformation matrices must be tuple instances, " + "not %s." % type(value).__name__ + ) if not len(value) == 6: - raise ValueError("Transformation matrices must contain six values, " - "not %d." % len(value)) + raise ValueError( + "Transformation matrices must contain six values, " "not %d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Transformation matrix values must be instances " - "of :ref:`type-int-float`, not %s." - % type(v).__name__) + raise TypeError( + "Transformation matrix values must be instances " + "of :ref:`type-int-float`, not %s." % type(v).__name__ + ) return tuple(float(v) for v in value) -def normalizeTransformationOffset(value: PairCollectionType[IntFloatType] - ) -> PairType[IntFloatType]: +def normalizeTransformationOffset( + value: PairCollectionType[IntFloatType], +) -> PairType[IntFloatType]: """Normalize a transformation offset. :param value: The transformation offset to normalize as a :class:`list` @@ -1227,24 +1300,30 @@ def normalizeTransformationSkewAngle(value: TransformationType) -> PairType[floa """ if not isinstance(value, (int, float, list, tuple)): - raise TypeError("Transformation skew angle must be an int, float, or " - "tuple instances, not %s." % type(value).__name__) + raise TypeError( + "Transformation skew angle must be an int, float, or " + "tuple instances, not %s." % type(value).__name__ + ) if isinstance(value, (int, float)): value = (float(value), 0) else: if not len(value) == 2: - raise ValueError("Transformation skew angle tuple must contain " - "two values, not %d." % len(value)) + raise ValueError( + "Transformation skew angle tuple must contain " + "two values, not %d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Transformation skew angle tuple values must " - "be an :ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Transformation skew angle tuple values must " + "be an :ref:`type-int-float`, not %s." % type(value).__name__ + ) value = tuple(float(v) for v in value) for v in value: if abs(v) > 360: - raise ValueError("Transformation skew angle must be between -360 " - "and 360.") + raise ValueError( + "Transformation skew angle must be between -360 " "and 360." + ) return tuple(float(v + 360) if v < 0 else float(v) for v in value) @@ -1266,19 +1345,24 @@ def normalizeTransformationScale(value: TransformationType) -> PairType[float]: """ if not isinstance(value, (int, float, list, tuple)): - raise TypeError("Transformation scale must be an int, float, or tuple " - "instances, not %s." % type(value).__name__) + raise TypeError( + "Transformation scale must be an int, float, or tuple " + "instances, not %s." % type(value).__name__ + ) if isinstance(value, (int, float)): value = (float(value), float(value)) else: if not len(value) == 2: - raise ValueError("Transformation scale tuple must contain two " - "values, not %d." % len(value)) + raise ValueError( + "Transformation scale tuple must contain two " + "values, not %d." % len(value) + ) for v in value: if not isinstance(v, (int, float)): - raise TypeError("Transformation scale tuple values must be an " - ":ref:`type-int-float`, not %s." - % type(value).__name__) + raise TypeError( + "Transformation scale tuple values must be an " + ":ref:`type-int-float`, not %s." % type(value).__name__ + ) value = tuple(float(v) for v in value) return value @@ -1297,6 +1381,7 @@ def normalizeVisualRounding(value: IntFloatType) -> int: """ if not isinstance(value, (int, float)): - raise TypeError("Value to round must be an int or float, not %s." - % type(value).__name__) + raise TypeError( + "Value to round must be an int or float, not %s." % type(value).__name__ + ) return otRound(value) diff --git a/Lib/fontParts/base/point.py b/Lib/fontParts/base/point.py index 33c65f60..6b49afe9 100644 --- a/Lib/fontParts/base/point.py +++ b/Lib/fontParts/base/point.py @@ -9,14 +9,14 @@ SelectionMixin, IdentifierMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.deprecated import DeprecatedPoint, RemovedPoint -from fontParts.base.annotations import( +from fontParts.base.annotations import ( QuintupleType, SextupleCollectionType, - IntFloatType + IntFloatType, ) if TYPE_CHECKING: @@ -26,14 +26,15 @@ from fontParts.base.contour import BaseContour -class BasePoint(BaseObject, - TransformationMixin, - PointPositionMixin, - SelectionMixin, - IdentifierMixin, - DeprecatedPoint, - RemovedPoint): - +class BasePoint( + BaseObject, + TransformationMixin, + PointPositionMixin, + SelectionMixin, + IdentifierMixin, + DeprecatedPoint, + RemovedPoint, +): """Represent the basis for a point object. This object is almost always created with :meth:`BaseContour.appendPoint`, @@ -46,13 +47,7 @@ class BasePoint(BaseObject, """ - copyAttributes: QuintupleType[str] = ( - "type", - "smooth", - "x", - "y", - "name" - ) + copyAttributes: QuintupleType[str] = ("type", "smooth", "x", "y", "name") def _reprContents(self) -> list[str]: contents = [ @@ -88,7 +83,7 @@ def _reprContents(self) -> list[str]: >>> contour = point.contour - """ + """, ) def _get_contour(self) -> Optional[BaseContour]: @@ -120,7 +115,7 @@ def _set_contour(self, contour: Optional[BaseContour]) -> None: >>> glyph = point.glyph - """ + """, ) def _get_glyph(self) -> Optional[BaseObject]: @@ -143,7 +138,7 @@ def _get_glyph(self) -> Optional[BaseObject]: >>> layer = point.layer - """ + """, ) def _get_layer(self) -> Optional[BaseObject]: @@ -155,7 +150,6 @@ def _get_layer(self) -> Optional[BaseObject]: font: dynamicProperty = dynamicProperty( "font", - """Get the point's parent font object. This property is read-only. @@ -167,7 +161,7 @@ def _get_layer(self) -> Optional[BaseObject]: >>> font = point.font - """ + """, ) def _get_font(self) -> Optional[BaseObject]: @@ -200,7 +194,8 @@ def _get_font(self) -> Optional[BaseObject]: :return: A :class:`str` representing the type of the point. - """) + """, + ) def _get_base_type(self) -> str: value = self._get_type() @@ -265,7 +260,7 @@ def _set_type(self, value: str) -> None: False >>> point.smooth = True - """ + """, ) def _get_base_smooth(self) -> bool: @@ -330,7 +325,7 @@ def _set_smooth(self, value: bool) -> None: 100 >>> point.x = 101 - """ + """, ) def _get_base_x(self) -> IntFloatType: @@ -399,7 +394,7 @@ def _set_x(self, value: IntFloatType) -> None: 100 >>> point.y = 101 - """ + """, ) def _get_base_y(self) -> IntFloatType: @@ -470,7 +465,7 @@ def _set_y(self, value: IntFloatType) -> None: >>> point.index 0 - """ + """, ) def _get_base_index(self) -> Optional[int]: @@ -515,7 +510,7 @@ def _get_index(self) -> Optional[int]: 'my point' >>> point.name = None - """ + """, ) def _get_base_name(self) -> Optional[str]: @@ -569,9 +564,9 @@ def _set_name(self, value: str) -> None: # Transformation # -------------- - def _transformBy(self, - matrix: SextupleCollectionType[IntFloatType], - **kwargs: Any) -> None: + def _transformBy( + self, matrix: SextupleCollectionType[IntFloatType], **kwargs: Any + ) -> None: r"""Transform the native point. This is the environment implementation of :meth:`BasePoint.transformBy`. diff --git a/Lib/fontParts/base/segment.py b/Lib/fontParts/base/segment.py index 0622af40..db26a0e5 100644 --- a/Lib/fontParts/base/segment.py +++ b/Lib/fontParts/base/segment.py @@ -5,7 +5,7 @@ InterpolationMixin, SelectionMixin, dynamicProperty, - reference + reference, ) from fontParts.base import normalizers from fontParts.base.deprecated import DeprecatedSegment, RemovedSegment @@ -13,14 +13,13 @@ class BaseSegment( - BaseObject, - TransformationMixin, - InterpolationMixin, - SelectionMixin, - DeprecatedSegment, - RemovedSegment - ): - + BaseObject, + TransformationMixin, + InterpolationMixin, + SelectionMixin, + DeprecatedSegment, + RemovedSegment, +): def _setPoints(self, points): if hasattr(self, "_points"): raise AssertionError("segment has points") @@ -111,10 +110,13 @@ def __eq__(self, other): # Identification # -------------- - index = dynamicProperty("base_index", - ("The index of the segment within the ordered " - "list of the parent contour's segments.") - ) + index = dynamicProperty( + "base_index", + ( + "The index of the segment within the ordered " + "list of the parent contour's segments." + ), + ) def _get_base_index(self): if self.contour is None: @@ -135,10 +137,10 @@ def _get_index(self): # Attributes # ---------- - type = dynamicProperty("base_type", - ("The segment type. The possible types are " - "move, line, curve, qcurve.") - ) + type = dynamicProperty( + "base_type", + ("The segment type. The possible types are " "move, line, curve, qcurve."), + ) def _get_base_type(self): value = self._get_type() @@ -198,10 +200,9 @@ def _set_type(self, newType): self._setPoints((off1, off2, on)) self.onCurve.type = newType - smooth = dynamicProperty("base_smooth", - ("Boolean indicating if the segment is " - "smooth or not.") - ) + smooth = dynamicProperty( + "base_smooth", ("Boolean indicating if the segment is " "smooth or not.") + ) def _get_base_smooth(self): value = self._get_smooth() @@ -266,8 +267,7 @@ def _len(self, **kwargs): """ return len(self.points) - points = dynamicProperty("base_points", - "A list of points in the segment.") + points = dynamicProperty("base_points", "A list of points in the segment.") def _get_base_points(self): return tuple(self._get_points()) @@ -280,8 +280,7 @@ def _get_points(self): return tuple() return tuple(self._points) - onCurve = dynamicProperty("base_onCurve", - "The on curve point in the segment.") + onCurve = dynamicProperty("base_onCurve", "The on curve point in the segment.") def _get_base_onCurve(self): return self._get_onCurve() @@ -295,8 +294,7 @@ def _get_onCurve(self): return None return value - offCurve = dynamicProperty("base_offCurve", - "The off curve points in the segment.") + offCurve = dynamicProperty("base_offCurve", "The off curve points in the segment.") def _get_base_offCurve(self): """ diff --git a/Lib/fontParts/fontshell/anchor.py b/Lib/fontParts/fontshell/anchor.py index 2d7c3596..a06ce64c 100644 --- a/Lib/fontParts/fontshell/anchor.py +++ b/Lib/fontParts/fontshell/anchor.py @@ -4,7 +4,6 @@ class RAnchor(RBaseObject, BaseAnchor): - wrapClass = defcon.Anchor def _init(self, wrap=None): diff --git a/Lib/fontParts/fontshell/base.py b/Lib/fontParts/fontshell/base.py index 90919ac6..258613d8 100644 --- a/Lib/fontParts/fontshell/base.py +++ b/Lib/fontParts/fontshell/base.py @@ -1,5 +1,4 @@ class RBaseObject(object): - wrapClass = None def _init(self, wrap=None): diff --git a/Lib/fontParts/fontshell/component.py b/Lib/fontParts/fontshell/component.py index 9cfb38d5..6ab5dd41 100644 --- a/Lib/fontParts/fontshell/component.py +++ b/Lib/fontParts/fontshell/component.py @@ -4,7 +4,6 @@ class RComponent(RBaseObject, BaseComponent): - wrapClass = defcon.Component # ---------- diff --git a/Lib/fontParts/fontshell/contour.py b/Lib/fontParts/fontshell/contour.py index a8ab4474..cabdb5db 100644 --- a/Lib/fontParts/fontshell/contour.py +++ b/Lib/fontParts/fontshell/contour.py @@ -7,7 +7,6 @@ class RContour(RBaseObject, BaseContour): - wrapClass = defcon.Contour pointClass = RPoint segmentClass = RSegment @@ -93,8 +92,16 @@ def _getPoint(self, index, **kwargs): point = contour[index] return self.pointClass(point) - def _insertPoint(self, index, position, type=None, smooth=None, - name=None, identifier=None, **kwargs): + def _insertPoint( + self, + index, + position, + type=None, + smooth=None, + name=None, + identifier=None, + **kwargs, + ): point = self.pointClass() point.x = position[0] point.y = position[1] diff --git a/Lib/fontParts/fontshell/features.py b/Lib/fontParts/fontshell/features.py index 2ad2c8d9..30fb7d37 100644 --- a/Lib/fontParts/fontshell/features.py +++ b/Lib/fontParts/fontshell/features.py @@ -4,7 +4,6 @@ class RFeatures(RBaseObject, BaseFeatures): - wrapClass = defcon.Features def _get_text(self): diff --git a/Lib/fontParts/fontshell/font.py b/Lib/fontParts/fontshell/font.py index 5a7c1e6e..cd4d22bb 100644 --- a/Lib/fontParts/fontshell/font.py +++ b/Lib/fontParts/fontshell/font.py @@ -12,7 +12,6 @@ class RFont(RBaseObject, BaseFont): - wrapClass = defcon.Font infoClass = RInfo groupsClass = RGroups @@ -46,9 +45,17 @@ def _get_path(self, **kwargs): # save - def _save(self, path=None, showProgress=False, - formatVersion=None, fileStructure=None, **kwargs): - self.naked().save(path=path, formatVersion=formatVersion, structure=fileStructure) + def _save( + self, + path=None, + showProgress=False, + formatVersion=None, + fileStructure=None, + **kwargs, + ): + self.naked().save( + path=path, formatVersion=formatVersion, structure=fileStructure + ) # close @@ -151,7 +158,9 @@ def _getGuideline(self, index, **kwargs): guideline = self.naked().guidelines[index] return self.guidelineClass(guideline) - def _appendGuideline(self, position, angle, name=None, color=None, identifier=None, **kwargs): + def _appendGuideline( + self, position, angle, name=None, color=None, identifier=None, **kwargs + ): guideline = self.guidelineClass().naked() guideline.x = position[0] guideline.y = position[1] diff --git a/Lib/fontParts/fontshell/glyph.py b/Lib/fontParts/fontshell/glyph.py index bb61eb21..333177c8 100644 --- a/Lib/fontParts/fontshell/glyph.py +++ b/Lib/fontParts/fontshell/glyph.py @@ -9,12 +9,14 @@ from fontParts.fontshell.guideline import RGuideline from fontParts.fontshell.image import RImage from fontParts.fontshell.lib import RLib -from fontTools.ufoLib.glifLib import (GlifLibError, readGlyphFromString, - writeGlyphToString) +from fontTools.ufoLib.glifLib import ( + GlifLibError, + readGlyphFromString, + writeGlyphToString, +) class RGlyph(RBaseObject, BaseGlyph): - wrapClass = defcon.Glyph contourClass = RContour componentClass = RComponent @@ -141,8 +143,13 @@ def _removeOverlap(self, **kwargs): for point in contour.points: if point.type == "qcurve": raise TypeError("fontshell can't removeOverlap for quadratics") - self.clear(contours=True, components=False, - anchors=False, guidelines=False, image=False) + self.clear( + contours=True, + components=False, + anchors=False, + guidelines=False, + image=False, + ) booleanOperations.union(contours, self.getPointPen()) def _correctDirection(self, trueType=False, **kwargs): @@ -201,7 +208,9 @@ def _getGuideline(self, index, **kwargs): guideline = glyph.guidelines[index] return self.guidelineClass(guideline) - def _appendGuideline(self, position, angle, name=None, color=None, identifier=None, **kwargs): + def _appendGuideline( + self, position, angle, name=None, color=None, identifier=None, **kwargs + ): glyph = self.naked() guideline = self.guidelineClass().naked() guideline.x = position[0] @@ -312,7 +321,7 @@ def _loadFromGLIF(self, glifData, validate=True): aString=glifData, glyphObject=self.naked(), pointPen=self.getPointPen(), - validate=validate + validate=validate, ) except GlifLibError: raise FontPartsError("Not valid glif data") @@ -323,5 +332,5 @@ def _dumpToGLIF(self, glyphFormatVersion): glyphName=glyph.name, glyphObject=glyph, drawPointsFunc=glyph.drawPoints, - formatVersion=glyphFormatVersion + formatVersion=glyphFormatVersion, ) diff --git a/Lib/fontParts/fontshell/groups.py b/Lib/fontParts/fontshell/groups.py index 0986be93..66c86b2c 100644 --- a/Lib/fontParts/fontshell/groups.py +++ b/Lib/fontParts/fontshell/groups.py @@ -4,7 +4,6 @@ class RGroups(RBaseObject, BaseGroups): - wrapClass = defcon.Groups def _get_side1KerningGroups(self): diff --git a/Lib/fontParts/fontshell/guideline.py b/Lib/fontParts/fontshell/guideline.py index 03f3e46d..57ba3aea 100644 --- a/Lib/fontParts/fontshell/guideline.py +++ b/Lib/fontParts/fontshell/guideline.py @@ -4,7 +4,6 @@ class RGuideline(RBaseObject, BaseGuideline): - wrapClass = defcon.Guideline def _init(self, wrap=None): diff --git a/Lib/fontParts/fontshell/image.py b/Lib/fontParts/fontshell/image.py index 4a9fead9..4cc664e8 100644 --- a/Lib/fontParts/fontshell/image.py +++ b/Lib/fontParts/fontshell/image.py @@ -4,7 +4,6 @@ class RImage(RBaseObject, BaseImage): - wrapClass = defcon.Image _orphanData = None _orphanColor = None @@ -53,6 +52,7 @@ def _get_data(self): def _set_data(self, value): from fontTools.ufoLib.validators import pngValidator + if not isinstance(value, bytes): raise FontPartsError("The image data provided is not valid.") if not pngValidator(data=value)[0]: diff --git a/Lib/fontParts/fontshell/info.py b/Lib/fontParts/fontshell/info.py index d4033f06..fa988865 100644 --- a/Lib/fontParts/fontshell/info.py +++ b/Lib/fontParts/fontshell/info.py @@ -4,7 +4,6 @@ class RInfo(RBaseObject, BaseInfo): - wrapClass = defcon.Info def _getAttr(self, attr): diff --git a/Lib/fontParts/fontshell/kerning.py b/Lib/fontParts/fontshell/kerning.py index 99e32442..080b7c5e 100644 --- a/Lib/fontParts/fontshell/kerning.py +++ b/Lib/fontParts/fontshell/kerning.py @@ -4,7 +4,6 @@ class RKerning(RBaseObject, BaseKerning): - wrapClass = defcon.Kerning def _items(self): diff --git a/Lib/fontParts/fontshell/layer.py b/Lib/fontParts/fontshell/layer.py index 2f8b8c0e..84162134 100644 --- a/Lib/fontParts/fontshell/layer.py +++ b/Lib/fontParts/fontshell/layer.py @@ -6,7 +6,6 @@ class RLayer(RBaseObject, BaseLayer): - wrapClass = defcon.Layer libClass = RLib glyphClass = RGlyph diff --git a/Lib/fontParts/fontshell/lib.py b/Lib/fontParts/fontshell/lib.py index 611197fb..dadf870a 100644 --- a/Lib/fontParts/fontshell/lib.py +++ b/Lib/fontParts/fontshell/lib.py @@ -4,7 +4,6 @@ class RLib(RBaseObject, BaseLib): - wrapClass = defcon.Lib def _items(self): diff --git a/Lib/fontParts/fontshell/point.py b/Lib/fontParts/fontshell/point.py index a18a34af..14cbba5f 100644 --- a/Lib/fontParts/fontshell/point.py +++ b/Lib/fontParts/fontshell/point.py @@ -4,7 +4,6 @@ class RPoint(RBaseObject, BasePoint): - wrapClass = defcon.Point def _init(self, wrap=None): @@ -18,7 +17,7 @@ def _postChangeNotification(self): return contour.naked().postNotification("Contour.PointsChanged") self.changed() - + def changed(self): self.contour.naked().dirty = True @@ -96,7 +95,11 @@ def _getIdentifier(self): contour.generateIdentifierForPoint(point) value = point.identifier else: - raise FontPartsError(("An identifier can not be generated " - "for this point because it does not " - "belong to a contour.")) + raise FontPartsError( + ( + "An identifier can not be generated " + "for this point because it does not " + "belong to a contour." + ) + ) return value diff --git a/Lib/fontParts/fontshell/test.py b/Lib/fontParts/fontshell/test.py index f0f5fed8..35e97a9f 100644 --- a/Lib/fontParts/fontshell/test.py +++ b/Lib/fontParts/fontshell/test.py @@ -22,6 +22,7 @@ # behavior with a small subclasses for testing # purposes only. + def _get_selected(self): if isinstance(self, FSTestSegment): for point in self.points: @@ -59,49 +60,41 @@ def _set_selected(self, value): class FSTestPoint(RPoint): - _get_selected = _get_selected _set_selected = _set_selected class FSTestBPoint(RBPoint): - _get_selected = _get_selected _set_selected = _set_selected class FSTestSegment(RSegment): - _get_selected = _get_selected _set_selected = _set_selected class FSTestGuideline(RGuideline): - _get_selected = _get_selected _set_selected = _set_selected class FSTestImage(RImage): - _get_selected = _get_selected _set_selected = _set_selected class FSTestAnchor(RAnchor): - _get_selected = _get_selected _set_selected = _set_selected class FSTestComponent(RComponent): - _get_selected = _get_selected _set_selected = _set_selected class FSTestContour(RContour): - segmentClass = FSTestSegment bPointClass = FSTestBPoint pointClass = FSTestPoint @@ -110,7 +103,6 @@ class FSTestContour(RContour): class FSTestGlyph(RGlyph): - contourClass = FSTestContour componentClass = FSTestComponent anchorClass = FSTestAnchor @@ -120,14 +112,12 @@ class FSTestGlyph(RGlyph): class FSTestLayer(RLayer): - glyphClass = FSTestGlyph _get_selected = _get_selected _set_selected = _set_selected class FSTestFont(RFont): - layerClass = FSTestLayer guidelineClass = FSTestGuideline _get_selected = _get_selected @@ -162,6 +152,7 @@ def fontshellObjectGenerator(cls): if __name__ == "__main__": import sys + if {"-v", "--verbose"}.intersection(sys.argv): verbosity = 2 else: diff --git a/Lib/fontParts/test/__init__.py b/Lib/fontParts/test/__init__.py index 85857bad..f7b9b76d 100644 --- a/Lib/fontParts/test/__init__.py +++ b/Lib/fontParts/test/__init__.py @@ -43,7 +43,7 @@ def testEnvironment(objectGenerator, inApp=False, verbosity=1, testNormalizers=T test_guideline, test_deprecated, test_color, - test_world + test_world, ] if testNormalizers: modules.append(test_normalizers) diff --git a/Lib/fontParts/test/legacyPointPen.py b/Lib/fontParts/test/legacyPointPen.py index 8297c3e9..24ed857f 100644 --- a/Lib/fontParts/test/legacyPointPen.py +++ b/Lib/fontParts/test/legacyPointPen.py @@ -2,7 +2,6 @@ class LegacyPointPen(RecordingPointPen): - """ A point pen that accepts only the original arguments in the various methods. @@ -15,9 +14,9 @@ def endPath(self): super(LegacyPointPen, self).endPath() def addPoint(self, pt, segmentType=None, smooth=False, name=None): - super(LegacyPointPen, self).addPoint(pt, - segmentType=segmentType, - smooth=smooth, name=name) + super(LegacyPointPen, self).addPoint( + pt, segmentType=segmentType, smooth=smooth, name=name + ) def addComponent(self, baseGlyphName, transformation): super(LegacyPointPen, self).addComponent(baseGlyphName, transformation) diff --git a/Lib/fontParts/test/test_anchor.py b/Lib/fontParts/test/test_anchor.py index 008daf57..f2e762bb 100644 --- a/Lib/fontParts/test/test_anchor.py +++ b/Lib/fontParts/test/test_anchor.py @@ -4,7 +4,6 @@ class TestAnchor(unittest.TestCase): - def getAnchor_generic(self): anchor, _ = self.objectGenerator("anchor") anchor.name = "Anchor Attribute Test" @@ -59,8 +58,8 @@ def test_get(self): def test_set_valid(self): anchor = self.getAnchor_generic() - anchor.name = u"foo" - self.assertEqual(anchor.name, u"foo") + anchor.name = "foo" + self.assertEqual(anchor.name, "foo") def test_set_none(self): anchor = self.getAnchor_generic() @@ -483,41 +482,27 @@ def test_round_at_half(self): def test_hash_object_self(self): anchor_one = self.getAnchor_generic() - self.assertEqual( - hash(anchor_one), - hash(anchor_one) - ) + self.assertEqual(hash(anchor_one), hash(anchor_one)) def test_hash_object_other(self): anchor_one = self.getAnchor_generic() anchor_two = self.getAnchor_generic() - self.assertNotEqual( - hash(anchor_one), - hash(anchor_two) - ) + self.assertNotEqual(hash(anchor_one), hash(anchor_two)) def test_hash_object_self_variable_assignment(self): anchor_one = self.getAnchor_generic() a = anchor_one - self.assertEqual( - hash(anchor_one), - hash(a) - ) + self.assertEqual(hash(anchor_one), hash(a)) def test_hash_object_other_variable_assignment(self): anchor_one = self.getAnchor_generic() anchor_two = self.getAnchor_generic() a = anchor_one - self.assertNotEqual( - hash(anchor_two), - hash(a) - ) + self.assertNotEqual(hash(anchor_two), hash(a)) def test_is_hashable(self): anchor_one = self.getAnchor_generic() - self.assertTrue( - isinstance(anchor_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(anchor_one, collections.abc.Hashable)) # ------- # Parents @@ -529,10 +514,7 @@ def test_get_parent_font(self): glyph = layer.newGlyph("X") anchor = glyph.appendAnchor("anchor 0", (0, 0)) self.assertIsNotNone(anchor.font) - self.assertEqual( - anchor.font, - font - ) + self.assertEqual(anchor.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -545,10 +527,7 @@ def test_get_parent_layer(self): glyph = layer.newGlyph("X") anchor = glyph.appendAnchor("anchor 0", (0, 0)) self.assertIsNotNone(anchor.layer) - self.assertEqual( - anchor.layer, - layer - ) + self.assertEqual(anchor.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -560,10 +539,7 @@ def test_get_parent_glyph(self): glyph, _ = self.objectGenerator("glyph") anchor = glyph.appendAnchor("anchor 0", (0, 0)) self.assertIsNotNone(anchor.glyph) - self.assertEqual( - anchor.glyph, - glyph - ) + self.assertEqual(anchor.glyph, glyph) def test_get_parent_noGlyph(self): anchor, _ = self.objectGenerator("anchor") @@ -576,10 +552,7 @@ def test_set_parent_glyph(self): anchor = self.getAnchor_generic() anchor.glyph = glyph self.assertIsNotNone(anchor.glyph) - self.assertEqual( - anchor.glyph, - glyph - ) + self.assertEqual(anchor.glyph, glyph) def test_set_parent_glyph_none(self): anchor, _ = self.objectGenerator("anchor") @@ -599,36 +572,24 @@ def test_set_parent_glyph_exists(self): def test_object_equal_self(self): anchor_one = self.getAnchor_generic() - self.assertEqual( - anchor_one, - anchor_one - ) + self.assertEqual(anchor_one, anchor_one) def test_object_not_equal_other(self): anchor_one = self.getAnchor_generic() anchor_two = self.getAnchor_generic() - self.assertNotEqual( - anchor_one, - anchor_two - ) + self.assertNotEqual(anchor_one, anchor_two) def test_object_equal_variable_assignment_self(self): anchor_one = self.getAnchor_generic() a = anchor_one a.moveBy((-1, 2)) - self.assertEqual( - anchor_one, - a - ) + self.assertEqual(anchor_one, a) def test_object_not_equal_variable_assignment_other(self): anchor_one = self.getAnchor_generic() anchor_two = self.getAnchor_generic() a = anchor_one - self.assertNotEqual( - anchor_two, - a - ) + self.assertNotEqual(anchor_two, a) # --------- # Selection @@ -641,10 +602,7 @@ def test_selected_true(self): except NotImplementedError: return anchor.selected = True - self.assertEqual( - anchor.selected, - True - ) + self.assertEqual(anchor.selected, True) def test_selected_false(self): anchor = self.getAnchor_generic() @@ -652,7 +610,4 @@ def test_selected_false(self): anchor.selected = False except NotImplementedError: return - self.assertEqual( - anchor.selected, - False - ) + self.assertEqual(anchor.selected, False) diff --git a/Lib/fontParts/test/test_bPoint.py b/Lib/fontParts/test/test_bPoint.py index 9d33daca..05f7bd18 100644 --- a/Lib/fontParts/test/test_bPoint.py +++ b/Lib/fontParts/test/test_bPoint.py @@ -4,7 +4,6 @@ class TestBPoint(unittest.TestCase): - def getBPoint_corner(self): contour, _ = self.objectGenerator("contour") contour.appendPoint((0, 0), "move") @@ -98,10 +97,7 @@ def test_get_parent_font(self): contour = glyph.contours[0] bPoint = contour.bPoints[1] self.assertIsNotNone(bPoint.font) - self.assertEqual( - bPoint.font, - font - ) + self.assertEqual(bPoint.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -126,10 +122,7 @@ def test_get_parent_layer(self): contour = glyph.contours[0] bPoint = contour.bPoints[1] self.assertIsNotNone(bPoint.layer) - self.assertEqual( - bPoint.layer, - layer - ) + self.assertEqual(bPoint.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -153,10 +146,7 @@ def test_get_parent_glyph(self): contour = glyph.contours[0] bPoint = contour.bPoints[1] self.assertIsNotNone(bPoint.glyph) - self.assertEqual( - bPoint.glyph, - glyph - ) + self.assertEqual(bPoint.glyph, glyph) def test_get_parent_noGlyph(self): contour, _ = self.objectGenerator("contour") @@ -173,10 +163,7 @@ def test_get_parent_contour(self): contour.appendPoint((303, 0), "line") bPoint = contour.bPoints[1] self.assertIsNotNone(bPoint.contour) - self.assertEqual( - bPoint.contour, - contour - ) + self.assertEqual(bPoint.contour, contour) def test_get_parent_noContour(self): bPoint, _ = self.objectGenerator("bPoint") @@ -213,10 +200,7 @@ def test_set_parent_contour(self): bPoint, _ = self.objectGenerator("bPoint") bPoint.contour = contour self.assertIsNotNone(bPoint.contour) - self.assertEqual( - bPoint.contour, - contour - ) + self.assertEqual(bPoint.contour, contour) def test_set_already_set_parent_contour(self): contour, _ = self.objectGenerator("contour") @@ -253,93 +237,60 @@ def test_get_parent_font_noContour(self): def test_get_type_corner(self): bPoint = self.getBPoint_corner() - self.assertEqual( - bPoint.type, - "corner" - ) + self.assertEqual(bPoint.type, "corner") def test_get_type_curve(self): bPoint = self.getBPoint_curve() - self.assertEqual( - bPoint.type, - "curve" - ) + self.assertEqual(bPoint.type, "curve") def test_set_type_corner(self): bPoint = self.getBPoint_curve() bPoint.type = "corner" - self.assertEqual( - bPoint.type, - "corner" - ) + self.assertEqual(bPoint.type, "corner") def test_set_type_curve(self): bPoint = self.getBPoint_corner() bPoint.type = "curve" - self.assertEqual( - bPoint.type, - "curve" - ) + self.assertEqual(bPoint.type, "curve") def test_type_not_equal(self): bPoint = self.getBPoint_corner() - self.assertNotEqual( - bPoint.type, - "curve" - ) + self.assertNotEqual(bPoint.type, "curve") def test_set_bcpOutIn_type_change(self): bPoint = self.getBPoint_curve() bPoint.bcpOut = (0, 0) bPoint.bcpIn = (0, 0) - self.assertEqual( - bPoint.type, - "corner" - ) + self.assertEqual(bPoint.type, "corner") def test_set_bcpInOut_type_change(self): bPoint = self.getBPoint_curve() bPoint.bcpIn = (0, 0) bPoint.bcpOut = (0, 0) - self.assertEqual( - bPoint.type, - "corner" - ) + self.assertEqual(bPoint.type, "corner") # https://github.com/robotools/fontParts/issues/435 def test_smooth_move_type_issue435(self): contour = self.getContour() contour.points[0].smooth = True bPoint = contour.bPoints[0] - self.assertEqual( - bPoint.type, - "curve" - ) + self.assertEqual(bPoint.type, "curve") # anchor def test_get_anchor(self): bPoint = self.getBPoint_corner() - self.assertEqual( - bPoint.anchor, - (101, 202) - ) + self.assertEqual(bPoint.anchor, (101, 202)) def test_set_anchor_valid_tuple(self): bPoint = self.getBPoint_corner() bPoint.anchor = (51, 45) - self.assertEqual( - bPoint.anchor, - (51, 45) - ) + self.assertEqual(bPoint.anchor, (51, 45)) def test_set_anchor_valid_list(self): bPoint = self.getBPoint_corner() bPoint.anchor = [51, 45] - self.assertEqual( - bPoint.anchor, - (51, 45) - ) + self.assertEqual(bPoint.anchor, (51, 45)) def test_set_anchor_invalid_too_many_items(self): bPoint = self.getBPoint_corner() @@ -370,41 +321,26 @@ def test_set_anchor_invalidType_None(self): def test_get_bcpIn_corner(self): bPoint = self.getBPoint_corner() - self.assertEqual( - bPoint.bcpIn, - (0, 0) - ) + self.assertEqual(bPoint.bcpIn, (0, 0)) def test_get_bcpIn_curve(self): bPoint = self.getBPoint_curve() - self.assertEqual( - bPoint.bcpIn, - (-40, -12) - ) + self.assertEqual(bPoint.bcpIn, (-40, -12)) def test_set_bcpIn_corner_valid_tuple(self): bPoint = self.getBPoint_corner() bPoint.bcpIn = (51, 45) - self.assertEqual( - bPoint.bcpIn, - (51, 45) - ) + self.assertEqual(bPoint.bcpIn, (51, 45)) def test_set_bcpIn_corner_with_bcpOut(self): bPoint = self.getBPoint_corner_with_bcpOut() bPoint.bcpIn = (51, 45) - self.assertEqual( - bPoint.bcpIn, - (51, 45) - ) + self.assertEqual(bPoint.bcpIn, (51, 45)) def test_set_bcpIn_curve_valid_tuple(self): bPoint = self.getBPoint_curve() bPoint.bcpIn = (51, 45) - self.assertEqual( - bPoint.bcpIn, - (51, 45) - ) + self.assertEqual(bPoint.bcpIn, (51, 45)) def test_set_bcpIn_curve_firstPointOpenContour(self): bPoint = self.getBPoint_curve_firstPointOpenContour() @@ -414,10 +350,7 @@ def test_set_bcpIn_curve_firstPointOpenContour(self): def test_set_bcpIn_valid_list(self): bPoint = self.getBPoint_corner() bPoint.bcpIn = [51, 45] - self.assertEqual( - bPoint.bcpIn, - (51, 45) - ) + self.assertEqual(bPoint.bcpIn, (51, 45)) def test_set_bcpIn_invalid_too_many_items(self): bPoint = self.getBPoint_corner() @@ -432,7 +365,7 @@ def test_set_bcpIn_invalid_single_item_list(self): def test_set_bcpIn_invalid_single_item_tuple(self): bPoint = self.getBPoint_corner() with self.assertRaises(TypeError): - bPoint.bcpIn = (51) + bPoint.bcpIn = 51 def test_set_bcpIn_invalidType_int(self): bPoint = self.getBPoint_corner() @@ -448,49 +381,31 @@ def test_set_bcpIn_invalidType_None(self): def test_get_bcpOut_corner(self): bPoint = self.getBPoint_corner() - self.assertEqual( - bPoint.bcpOut, - (0, 0) - ) + self.assertEqual(bPoint.bcpOut, (0, 0)) def test_get_bcpOut_curve(self): bPoint = self.getBPoint_curve() - self.assertEqual( - bPoint.bcpOut, - (32, 10) - ) + self.assertEqual(bPoint.bcpOut, (32, 10)) def test_set_bcpOut_corner_valid_tuple(self): bPoint = self.getBPoint_corner() bPoint.bcpOut = (51, 45) - self.assertEqual( - bPoint.bcpOut, - (51, 45) - ) + self.assertEqual(bPoint.bcpOut, (51, 45)) def test_set_bcpOut_corner_with_bcpIn(self): bPoint = self.getBPoint_corner_with_bcpIn() bPoint.bcpOut = (51, 45) - self.assertEqual( - bPoint.bcpOut, - (51, 45) - ) + self.assertEqual(bPoint.bcpOut, (51, 45)) def test_set_bcpOut_curve_valid_tuple(self): bPoint = self.getBPoint_curve() bPoint.bcpOut = (51, 45) - self.assertEqual( - bPoint.bcpOut, - (51, 45) - ) + self.assertEqual(bPoint.bcpOut, (51, 45)) def test_set_bcpOut_valid_list(self): bPoint = self.getBPoint_curve() bPoint.bcpOut = [51, 45] - self.assertEqual( - bPoint.bcpOut, - (51, 45) - ) + self.assertEqual(bPoint.bcpOut, (51, 45)) def test_set_bcpOut_curve_lastPointOpenContour(self): bPoint = self.getBPoint_curve_lastPointOpenContour() @@ -510,7 +425,7 @@ def test_set_bcpOut_invalid_single_item_list(self): def test_set_bcpOut_invalid_single_item_tuple(self): bPoint = self.getBPoint_corner() with self.assertRaises(TypeError): - bPoint.bcpOut = (51) + bPoint.bcpOut = 51 def test_set_bcpOut_invalidType_int(self): bPoint = self.getBPoint_corner() @@ -538,10 +453,7 @@ def getBPoint_noParentContour(self): def test_get_index(self): bPoint = self.getBPoint_corner() - self.assertEqual( - bPoint.index, - 1 - ) + self.assertEqual(bPoint.index, 1) # def test_get_index_noParentContour(self): # bPoint = self.getBPoint_noParentContour() @@ -594,10 +506,7 @@ def test_getIdentifer_consistency(self): def test_hash(self): bPoint = self.getBPoint_corner() - self.assertEqual( - isinstance(bPoint, collections.abc.Hashable), - False - ) + self.assertEqual(isinstance(bPoint, collections.abc.Hashable), False) # -------- # Equality @@ -605,36 +514,24 @@ def test_hash(self): def test_object_equal_self(self): bPoint_one = self.getBPoint_corner() - self.assertEqual( - bPoint_one, - bPoint_one - ) + self.assertEqual(bPoint_one, bPoint_one) def test_object_not_equal_other(self): bPoint_one = self.getBPoint_corner() bPoint_two = self.getBPoint_corner() - self.assertNotEqual( - bPoint_one, - bPoint_two - ) + self.assertNotEqual(bPoint_one, bPoint_two) def test_object_equal_self_variable_assignment(self): bPoint_one = self.getBPoint_corner() a = bPoint_one a.anchor = (51, 45) - self.assertEqual( - bPoint_one, - a - ) + self.assertEqual(bPoint_one, a) def test_object_not_equal_other_variable_assignment(self): bPoint_one = self.getBPoint_corner() bPoint_two = self.getBPoint_corner() a = bPoint_one - self.assertNotEqual( - bPoint_two, - a - ) + self.assertNotEqual(bPoint_two, a) # --------- # Selection @@ -647,10 +544,7 @@ def test_selected_true(self): except NotImplementedError: return bPoint.selected = True - self.assertEqual( - bPoint.selected, - True - ) + self.assertEqual(bPoint.selected, True) def test_selected_false(self): bPoint = self.getBPoint_corner() @@ -659,10 +553,7 @@ def test_selected_false(self): except NotImplementedError: return bPoint.selected = False - self.assertEqual( - bPoint.selected, - False - ) + self.assertEqual(bPoint.selected, False) # ---- # Copy @@ -671,26 +562,17 @@ def test_selected_false(self): def test_copy_seperate_objects(self): bPoint = self.getBPoint_corner() copied = bPoint.copy() - self.assertIsNot( - bPoint, - copied - ) + self.assertIsNot(bPoint, copied) def test_copy_different_contour(self): bPoint = self.getBPoint_corner() copied = bPoint.copy() - self.assertIsNot( - bPoint.contour, - copied.contour - ) + self.assertIsNot(bPoint.contour, copied.contour) def test_copy_none_contour(self): bPoint = self.getBPoint_corner() copied = bPoint.copy() - self.assertEqual( - copied.contour, - None - ) + self.assertEqual(copied.contour, None) # def test_copy_same_type(self): # bPoint = self.getBPoint_corner() @@ -799,50 +681,32 @@ def test_copy_none_contour(self): def test_transformBy_valid_no_origin_anchor(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - bPoint.anchor, - (199.0, 608.0) - ) + self.assertEqual(bPoint.anchor, (199.0, 608.0)) def test_transformBy_valid_no_origin_bcpIn(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - bPoint.bcpIn, - (-80.0, -36.0) - ) + self.assertEqual(bPoint.bcpIn, (-80.0, -36.0)) def test_transformBy_valid_no_origin_bcpOut(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - bPoint.bcpOut, - (64.0, 30.0) - ) + self.assertEqual(bPoint.bcpOut, (64.0, 30.0)) def test_transformBy_valid_origin_anchor(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - bPoint.anchor, - (201.0, 402.0) - ) + self.assertEqual(bPoint.anchor, (201.0, 402.0)) def test_transformBy_valid_origin_bcpIn(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - bPoint.bcpIn, - (-80.0, -24.0) - ) + self.assertEqual(bPoint.bcpIn, (-80.0, -24.0)) def test_transformBy_valid_origin_bcpOut(self): bPoint = self.getBPoint_curve() bPoint.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - bPoint.bcpOut, - (64.0, 20.0) - ) + self.assertEqual(bPoint.bcpOut, (64.0, 20.0)) def test_transformBy_invalid_one_string_value(self): point = self.getBPoint_curve() @@ -864,28 +728,19 @@ def test_transformBy_invalid_int_value(self): def test_moveBy_valid_anchor(self): bPoint = self.getBPoint_curve() bPoint.moveBy((-1, 2)) - self.assertEqual( - bPoint.anchor, - (100.0, 204.0) - ) + self.assertEqual(bPoint.anchor, (100.0, 204.0)) def test_moveBy_noChange_bcpIn(self): bPoint = self.getBPoint_curve() bPoint.moveBy((-1, 2)) otherBPoint = self.getBPoint_curve() - self.assertEqual( - bPoint.bcpIn, - otherBPoint.bcpIn - ) + self.assertEqual(bPoint.bcpIn, otherBPoint.bcpIn) def test_moveBy_noChange_bcpOut(self): bPoint = self.getBPoint_curve() bPoint.moveBy((-1, 2)) otherBPoint = self.getBPoint_curve() - self.assertEqual( - bPoint.bcpOut, - otherBPoint.bcpOut - ) + self.assertEqual(bPoint.bcpOut, otherBPoint.bcpOut) def test_moveBy_invalid_one_string_value(self): bPoint = self.getBPoint_curve() @@ -907,42 +762,27 @@ def test_moveBy_invalid_int_value(self): def test_scaleBy_valid_one_value_no_origin_anchor(self): bPoint = self.getBPoint_curve() bPoint.scaleBy((-2)) - self.assertEqual( - bPoint.anchor, - (-202.0, -404.0) - ) + self.assertEqual(bPoint.anchor, (-202.0, -404.0)) def test_scaleBy_valid_two_values_no_origin_anchor(self): bPoint = self.getBPoint_curve() bPoint.scaleBy((-2, 3)) - self.assertEqual( - bPoint.anchor, - (-202.0, 606.0) - ) + self.assertEqual(bPoint.anchor, (-202.0, 606.0)) def test_scaleBy_valid_two_values_origin_anchor(self): bPoint = self.getBPoint_curve() bPoint.scaleBy((-2, 3), origin=(1, 2)) - self.assertEqual( - bPoint.anchor, - (-199.0, 602.0) - ) + self.assertEqual(bPoint.anchor, (-199.0, 602.0)) def test_scaleBy_valid_two_values_origin_bcpIn(self): bPoint = self.getBPoint_curve() bPoint.scaleBy((-2, 3), origin=(1, 2)) - self.assertEqual( - bPoint.bcpIn, - (80.0, -36.0) - ) + self.assertEqual(bPoint.bcpIn, (80.0, -36.0)) def test_scaleBy_valid_two_values_origin_bcpOut(self): bPoint = self.getBPoint_curve() bPoint.scaleBy((-2, 3), origin=(1, 2)) - self.assertEqual( - bPoint.bcpOut, - (-64.0, 30.0) - ) + self.assertEqual(bPoint.bcpOut, (-64.0, 30.0)) def test_invalid_one_string_value_scaleBy(self): bPoint = self.getBPoint_curve() @@ -966,7 +806,7 @@ def test_rotateBy_valid_no_origin_anchor(self): bPoint.rotateBy(45) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-71.418, 214.253] + [-71.418, 214.253], ) def test_rotateBy_valid_origin_anchor(self): @@ -974,7 +814,7 @@ def test_rotateBy_valid_origin_anchor(self): bPoint.rotateBy(45, origin=(1, 2)) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-69.711, 214.132] + [-69.711, 214.132], ) def test_rotateBy_valid_origin_bcpIn(self): @@ -982,7 +822,7 @@ def test_rotateBy_valid_origin_bcpIn(self): bPoint.rotateBy(45, origin=(1, 2)) self.assertEqual( [(round(bPoint.bcpIn[0], 3)), (round(bPoint.bcpIn[1], 3))], - [-19.799, -36.77] + [-19.799, -36.77], ) def test_rotateBy_valid_origin_bcpOut(self): @@ -990,7 +830,7 @@ def test_rotateBy_valid_origin_bcpOut(self): bPoint.rotateBy(45, origin=(1, 2)) self.assertEqual( [(round(bPoint.bcpOut[0], 3)), (round(bPoint.bcpOut[1], 3))], - [15.556, 29.698] + [15.556, 29.698], ) def test_rotateBy_invalid_string_value(self): @@ -1015,7 +855,7 @@ def test_skewBy_valid_no_origin_one_value_anchor(self): bPoint.skewBy(100) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-1044.599, 202.0] + [-1044.599, 202.0], ) def test_skewBy_valid_no_origin_two_values_anchor(self): @@ -1023,7 +863,7 @@ def test_skewBy_valid_no_origin_two_values_anchor(self): bPoint.skewBy((100, 200)) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-1044.599, 238.761] + [-1044.599, 238.761], ) def test_skewBy_valid_origin_one_value_anchor(self): @@ -1031,7 +871,7 @@ def test_skewBy_valid_origin_one_value_anchor(self): bPoint.skewBy(100, origin=(1, 2)) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-1033.256, 202.0] + [-1033.256, 202.0], ) def test_skewBy_valid_origin_two_values_anchor(self): @@ -1039,7 +879,7 @@ def test_skewBy_valid_origin_two_values_anchor(self): bPoint.skewBy((100, 200), origin=(1, 2)) self.assertEqual( [(round(bPoint.anchor[0], 3)), (round(bPoint.anchor[1], 3))], - [-1033.256, 238.397] + [-1033.256, 238.397], ) def test_skewBy_valid_origin_two_values_bcpIn(self): @@ -1047,7 +887,7 @@ def test_skewBy_valid_origin_two_values_bcpIn(self): bPoint.skewBy((100, 200), origin=(1, 2)) self.assertEqual( [(round(bPoint.bcpIn[0], 3)), (round(bPoint.bcpIn[1], 3))], - [28.055, -26.559] + [28.055, -26.559], ) def test_skewBy_valid_origin_two_values_bcpOut(self): @@ -1055,7 +895,7 @@ def test_skewBy_valid_origin_two_values_bcpOut(self): bPoint.skewBy((100, 200), origin=(1, 2)) self.assertEqual( [(round(bPoint.bcpOut[0], 3)), (round(bPoint.bcpOut[1], 3))], - [-24.713, 21.647] + [-24.713, 21.647], ) def test_skewBy_invalid_string_value(self): @@ -1094,23 +934,14 @@ def getBPoint_curve_float(self): def test_round_anchor(self): bPoint = self.getBPoint_curve_float() bPoint.round() - self.assertEqual( - bPoint.anchor, - (102.0, 202.0) - ) + self.assertEqual(bPoint.anchor, (102.0, 202.0)) def test_round_bcpIn(self): bPoint = self.getBPoint_curve_float() bPoint.round() - self.assertEqual( - bPoint.bcpIn, - (-40.0, -11.0) - ) + self.assertEqual(bPoint.bcpIn, (-40.0, -11.0)) def test_round_bcpOut(self): bPoint = self.getBPoint_curve_float() bPoint.round() - self.assertEqual( - bPoint.bcpOut, - (32.0, 10.0) - ) + self.assertEqual(bPoint.bcpOut, (32.0, 10.0)) diff --git a/Lib/fontParts/test/test_color.py b/Lib/fontParts/test/test_color.py index 6bc8190b..def1a7e9 100644 --- a/Lib/fontParts/test/test_color.py +++ b/Lib/fontParts/test/test_color.py @@ -3,7 +3,6 @@ class TestComponent(unittest.TestCase): - def test_color_r(self): color = Color((1.0, 0, 0, 0)) self.assertEqual(color.r, 1.0) diff --git a/Lib/fontParts/test/test_component.py b/Lib/fontParts/test/test_component.py index 6d800347..201ece7b 100644 --- a/Lib/fontParts/test/test_component.py +++ b/Lib/fontParts/test/test_component.py @@ -4,7 +4,6 @@ class TestComponent(unittest.TestCase): - def getComponent_generic(self): layer, _ = self.objectGenerator("layer") glyph = layer.newGlyph("A") @@ -49,10 +48,7 @@ def test_get_parent_font(self): glyph = layer.newGlyph("X") component = glyph.appendComponent("A") self.assertIsNotNone(component.font) - self.assertEqual( - component.font, - font - ) + self.assertEqual(component.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -65,10 +61,7 @@ def test_get_parent_layer(self): glyph = layer.newGlyph("X") component = glyph.appendComponent("A") self.assertIsNotNone(component.layer) - self.assertEqual( - component.layer, - layer - ) + self.assertEqual(component.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -80,10 +73,7 @@ def test_get_parent_glyph(self): glyph, _ = self.objectGenerator("glyph") component = glyph.appendComponent("A") self.assertIsNotNone(component.glyph) - self.assertEqual( - component.glyph, - glyph - ) + self.assertEqual(component.glyph, glyph) def test_get_parent_noGlyph(self): component, _ = self.objectGenerator("component") @@ -96,10 +86,7 @@ def test_set_parent_glyph(self): component, _ = self.objectGenerator("component") component.glyph = glyph self.assertIsNotNone(component.glyph) - self.assertEqual( - component.glyph, - glyph - ) + self.assertEqual(component.glyph, glyph) def test_set_parent_glyph_none(self): component, _ = self.objectGenerator("component") @@ -121,18 +108,12 @@ def test_set_parent_glyph_exists(self): def test_baseGlyph_generic(self): component = self.getComponent_generic() - self.assertEqual( - component.baseGlyph, - "A" - ) + self.assertEqual(component.baseGlyph, "A") def test_baseGlyph_valid_set(self): component = self.getComponent_generic() component.baseGlyph = "B" - self.assertEqual( - component.baseGlyph, - "B" - ) + self.assertEqual(component.baseGlyph, "B") def test_baseGlyph_invalid_set_none(self): component = self.getComponent_generic() @@ -153,26 +134,17 @@ def test_baseGlyph_invalid_set_int(self): def test_transformation_generic(self): component = self.getComponent_generic() - self.assertEqual( - component.transformation, - (1, 0, 0, 1, 0, 0) - ) + self.assertEqual(component.transformation, (1, 0, 0, 1, 0, 0)) def test_transformation_valid_set_positive(self): component = self.getComponent_generic() component.transformation = (1, 2, 3, 4, 5, 6) - self.assertEqual( - component.transformation, - (1, 2, 3, 4, 5, 6) - ) + self.assertEqual(component.transformation, (1, 2, 3, 4, 5, 6)) def test_transformation_valid_set_negative(self): component = self.getComponent_generic() component.transformation = (-1, -2, -3, -4, -5, -6) - self.assertEqual( - component.transformation, - (-1, -2, -3, -4, -5, -6) - ) + self.assertEqual(component.transformation, (-1, -2, -3, -4, -5, -6)) def test_transformation_invalid_set_member(self): component = self.getComponent_generic() @@ -188,50 +160,32 @@ def test_transformation_invalid_set_none(self): def test_offset_generic(self): component = self.getComponent_generic() - self.assertEqual( - component.offset, - (0, 0) - ) + self.assertEqual(component.offset, (0, 0)) def test_offset_valid_set_zero(self): component = self.getComponent_generic() component.offset = (0, 0) - self.assertEqual( - component.offset, - (0, 0) - ) + self.assertEqual(component.offset, (0, 0)) def test_offset_valid_set_positive_positive(self): component = self.getComponent_generic() component.offset = (1, 2) - self.assertEqual( - component.offset, - (1, 2) - ) + self.assertEqual(component.offset, (1, 2)) def test_offset_valid_set_negative_positive(self): component = self.getComponent_generic() component.offset = (-1, 2) - self.assertEqual( - component.offset, - (-1, 2) - ) + self.assertEqual(component.offset, (-1, 2)) def test_offset_valid_set_positive_negative(self): component = self.getComponent_generic() component.offset = (1, -2) - self.assertEqual( - component.offset, - (1, -2) - ) + self.assertEqual(component.offset, (1, -2)) def test_offset_valid_set_negative_negative(self): component = self.getComponent_generic() component.offset = (-1, -2) - self.assertEqual( - component.offset, - (-1, -2) - ) + self.assertEqual(component.offset, (-1, -2)) def test_offset_invalid_set_real_bogus(self): component = self.getComponent_generic() @@ -257,50 +211,32 @@ def test_offset_invalid_set_none(self): def test_scale_generic(self): component = self.getComponent_generic() - self.assertEqual( - component.scale, - (1, 1) - ) + self.assertEqual(component.scale, (1, 1)) def test_scale_valid_set_zero(self): component = self.getComponent_generic() component.scale = (0, 0) - self.assertEqual( - component.scale, - (0, 0) - ) + self.assertEqual(component.scale, (0, 0)) def test_scale_valid_set_positive_positive(self): component = self.getComponent_generic() component.scale = (1, 2) - self.assertEqual( - component.scale, - (1, 2) - ) + self.assertEqual(component.scale, (1, 2)) def test_scale_valid_set_negative_positive(self): component = self.getComponent_generic() component.scale = (-1, 2) - self.assertEqual( - component.scale, - (-1, 2) - ) + self.assertEqual(component.scale, (-1, 2)) def test_scale_valid_set_positive_negative(self): component = self.getComponent_generic() component.scale = (1, -2) - self.assertEqual( - component.scale, - (1, -2) - ) + self.assertEqual(component.scale, (1, -2)) def test_scale_valid_set_negative_negative(self): component = self.getComponent_generic() component.scale = (-1, -2) - self.assertEqual( - component.scale, - (-1, -2) - ) + self.assertEqual(component.scale, (-1, -2)) def test_scale_invalid_set_real_bogus(self): component = self.getComponent_generic() @@ -353,28 +289,19 @@ def test_set_index_positive(self): glyph = self.getComponent_index() component = glyph.components[0] component.index = 2 - self.assertEqual( - [c.baseGlyph for c in glyph.components], - ["B", "A", "C"] - ) + self.assertEqual([c.baseGlyph for c in glyph.components], ["B", "A", "C"]) def test_set_index_pastLength(self): glyph = self.getComponent_index() component = glyph.components[0] component.index = 20 - self.assertEqual( - [c.baseGlyph for c in glyph.components], - ["B", "C", "A"] - ) + self.assertEqual([c.baseGlyph for c in glyph.components], ["B", "C", "A"]) def test_set_index_negative(self): glyph = self.getComponent_index() component = glyph.components[1] component.index = -1 - self.assertEqual( - [c.baseGlyph for c in glyph.components], - ["B", "A", "C"] - ) + self.assertEqual([c.baseGlyph for c in glyph.components], ["B", "A", "C"]) # identifier @@ -454,45 +381,43 @@ def test_copy_generated_identifier_different(self): def test_draw(self): from fontTools.pens.recordingPen import RecordingPen + component = self.getComponent_generic() component.transformation = (1, 2, 3, 4, 5, 6) pen = RecordingPen() component.draw(pen) - expected = [('addComponent', ('A', (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)))] - self.assertEqual( - pen.value, - expected - ) + expected = [("addComponent", ("A", (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)))] + self.assertEqual(pen.value, expected) # drawPoints def test_drawPoints(self): from fontPens.recordingPointPen import RecordingPointPen + component = self.getComponent_generic() component.transformation = (1, 2, 3, 4, 5, 6) identifier = component.getIdentifier() pointPen = RecordingPointPen() component.drawPoints(pointPen) - expected = [('addComponent', - (u'A', (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)), - {'identifier': identifier})] - self.assertEqual( - pointPen.value, - expected - ) + expected = [ + ( + "addComponent", + ("A", (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)), + {"identifier": identifier}, + ) + ] + self.assertEqual(pointPen.value, expected) def test_drawPoints_legacy(self): from .legacyPointPen import LegacyPointPen + component = self.getComponent_generic() component.transformation = (1, 2, 3, 4, 5, 6) component.getIdentifier() pointPen = LegacyPointPen() component.drawPoints(pointPen) - expected = [('addComponent', (u'A', (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)), {})] - self.assertEqual( - pointPen.value, - expected - ) + expected = [("addComponent", ("A", (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)), {})] + self.assertEqual(pointPen.value, expected) # -------------- # Transformation @@ -508,18 +433,12 @@ def getComponent_transform(self): def test_transformBy_valid_no_origin(self): component = self.getComponent_transform() component.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - component.transformation, - (2.0, 6.0, 6.0, 12.0, 7.0, 20.0) - ) + self.assertEqual(component.transformation, (2.0, 6.0, 6.0, 12.0, 7.0, 20.0)) def test_transformBy_valid_origin(self): component = self.getComponent_transform() component.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - component.transformation, - (2.0, 4.0, 6.0, 8.0, 9.0, 10.0) - ) + self.assertEqual(component.transformation, (2.0, 4.0, 6.0, 8.0, 9.0, 10.0)) def test_transformBy_invalid_one_string_value(self): component = self.getComponent_transform() @@ -541,10 +460,7 @@ def test_transformBy_invalid_int_value(self): def test_moveBy_valid(self): component = self.getComponent_transform() component.moveBy((-1, 2)) - self.assertEqual( - component.transformation, - (1.0, 2.0, 3.0, 4.0, 4.0, 8.0) - ) + self.assertEqual(component.transformation, (1.0, 2.0, 3.0, 4.0, 4.0, 8.0)) def test_moveBy_invalid_one_string_value(self): component = self.getComponent_transform() @@ -567,25 +483,18 @@ def test_scaleBy_valid_one_value_no_origin(self): component = self.getComponent_transform() component.scaleBy((-2)) self.assertEqual( - component.transformation, - (-2.0, -4.0, -6.0, -8.0, -10.0, -12.0) + component.transformation, (-2.0, -4.0, -6.0, -8.0, -10.0, -12.0) ) def test_scaleBy_valid_two_values_no_origin(self): component = self.getComponent_transform() component.scaleBy((-2, 3)) - self.assertEqual( - component.transformation, - (-2.0, 6.0, -6.0, 12.0, -10.0, 18.0) - ) + self.assertEqual(component.transformation, (-2.0, 6.0, -6.0, 12.0, -10.0, 18.0)) def test_scaleBy_valid_two_values_origin(self): component = self.getComponent_transform() component.scaleBy((-2, 3), origin=(1, 2)) - self.assertEqual( - component.transformation, - (-2.0, 6.0, -6.0, 12.0, -7.0, 14.0) - ) + self.assertEqual(component.transformation, (-2.0, 6.0, -6.0, 12.0, -7.0, 14.0)) def test_scaleBy_invalid_one_string_value(self): component = self.getComponent_transform() @@ -609,7 +518,7 @@ def test_rotateBy_valid_no_origin(self): component.rotateBy(45) self.assertEqual( [round(i, 3) for i in component.transformation], - [-0.707, 2.121, -0.707, 4.95, -0.707, 7.778] + [-0.707, 2.121, -0.707, 4.95, -0.707, 7.778], ) def test_rotateBy_valid_origin(self): @@ -617,7 +526,7 @@ def test_rotateBy_valid_origin(self): component.rotateBy(45, origin=(1, 2)) self.assertEqual( [round(i, 3) for i in component.transformation], - [-0.707, 2.121, -0.707, 4.95, 1.0, 7.657] + [-0.707, 2.121, -0.707, 4.95, 1.0, 7.657], ) def test_rotateBy_invalid_string_value(self): @@ -642,7 +551,7 @@ def test_skewBy_valid_no_origin_one_value(self): component.skewBy(100) self.assertEqual( [round(i, 3) for i in component.transformation], - [-10.343, 2.0, -19.685, 4.0, -29.028, 6.0] + [-10.343, 2.0, -19.685, 4.0, -29.028, 6.0], ) def test_skewBy_valid_no_origin_two_values(self): @@ -650,7 +559,7 @@ def test_skewBy_valid_no_origin_two_values(self): component.skewBy((100, 200)) self.assertEqual( [round(i, 3) for i in component.transformation], - [-10.343, 2.364, -19.685, 5.092, -29.028, 7.82] + [-10.343, 2.364, -19.685, 5.092, -29.028, 7.82], ) def test_skewBy_valid_origin_one_value(self): @@ -658,7 +567,7 @@ def test_skewBy_valid_origin_one_value(self): component.skewBy(100, origin=(1, 2)) self.assertEqual( [round(i, 3) for i in component.transformation], - [-10.343, 2.0, -19.685, 4.0, -17.685, 6.0] + [-10.343, 2.0, -19.685, 4.0, -17.685, 6.0], ) def test_skewBy_valid_origin_two_values(self): @@ -666,7 +575,7 @@ def test_skewBy_valid_origin_two_values(self): component.skewBy((100, 200), origin=(1, 2)) self.assertEqual( [round(i, 3) for i in component.transformation], - [-10.343, 2.364, -19.685, 5.092, -17.685, 7.456] + [-10.343, 2.364, -19.685, 5.092, -17.685, 7.456], ) # ------------- @@ -679,10 +588,7 @@ def test_round(self): component = self.getComponent_generic() component.transformation = (1.2, 2.2, 3.3, 4.4, 5.1, 6.6) component.round() - self.assertEqual( - component.transformation, - (1.2, 2.2, 3.3, 4.4, 5, 7) - ) + self.assertEqual(component.transformation, (1.2, 2.2, 3.3, 4.4, 5, 7)) # decompose @@ -693,6 +599,7 @@ def test_decompose_noParent(self): def test_decompose_digest(self): from fontPens.digestPointPen import DigestPointPen + component = self.getComponent_generic() glyph = component.glyph glyph.layer[component.baseGlyph] @@ -700,17 +607,14 @@ def test_decompose_digest(self): pointPen = DigestPointPen() glyph.drawPoints(pointPen) expected = ( - ('beginPath', None), - ((0, 0), u'line', False, 'point 0'), - ((0, 100), u'line', False, 'point 1'), - ((100, 100), u'line', False, 'point 2'), - ((100, 0), u'line', False, 'point 3'), - 'endPath' - ) - self.assertEqual( - pointPen.getDigest(), - expected + ("beginPath", None), + ((0, 0), "line", False, "point 0"), + ((0, 100), "line", False, "point 1"), + ((100, 100), "line", False, "point 2"), + ((100, 0), "line", False, "point 3"), + "endPath", ) + self.assertEqual(pointPen.getDigest(), expected) def test_decompose_identifiers(self): component = self.getComponent_generic() @@ -722,15 +626,13 @@ def test_decompose_identifiers(self): component.decompose() self.assertEqual( [point.identifier for point in glyph[0].points], - [point.identifier for point in baseGlyph[0].points] - ) - self.assertEqual( - glyph[0].identifier, - baseGlyph[0].identifier + [point.identifier for point in baseGlyph[0].points], ) + self.assertEqual(glyph[0].identifier, baseGlyph[0].identifier) def test_decompose_transformation(self): from fontPens.digestPointPen import DigestPointPen + component = self.getComponent_generic() component.scale = (2, 2) glyph = component.glyph @@ -739,17 +641,14 @@ def test_decompose_transformation(self): pointPen = DigestPointPen() glyph.drawPoints(pointPen) expected = ( - ('beginPath', None), - ((0, 0), u'line', False, 'point 0'), - ((0, 200), u'line', False, 'point 1'), - ((200, 200), u'line', False, 'point 2'), - ((200, 0), u'line', False, 'point 3'), - 'endPath' - ) - self.assertEqual( - pointPen.getDigest(), - expected + ("beginPath", None), + ((0, 0), "line", False, "point 0"), + ((0, 200), "line", False, "point 1"), + ((200, 200), "line", False, "point 2"), + ((200, 0), "line", False, "point 3"), + "endPath", ) + self.assertEqual(pointPen.getDigest(), expected) # ------------ # Data Queries @@ -759,10 +658,7 @@ def test_decompose_transformation(self): def test_bounds_get(self): component = self.getComponent_generic() - self.assertEqual( - component.bounds, - (0, 0, 100, 100) - ) + self.assertEqual(component.bounds, (0, 0, 100, 100)) def test_bounds_none(self): component = self.getComponent_generic() @@ -774,18 +670,12 @@ def test_bounds_none(self): def test_bounds_on_move(self): component = self.getComponent_generic() component.moveBy((0.1, -0.1)) - self.assertEqual( - component.bounds, - (0.1, -0.1, 100.1, 99.9) - ) + self.assertEqual(component.bounds, (0.1, -0.1, 100.1, 99.9)) def test_bounds_on_scale(self): component = self.getComponent_generic() component.scaleBy((2, 0.5)) - self.assertEqual( - component.bounds, - (0, 0, 200, 50) - ) + self.assertEqual(component.bounds, (0, 0, 200, 50)) def test_bounds_invalid_set(self): component = self.getComponent_generic() @@ -796,17 +686,11 @@ def test_bounds_invalid_set(self): def test_pointInside_true(self): component = self.getComponent_generic() - self.assertEqual( - component.pointInside((1, 1)), - True - ) + self.assertEqual(component.pointInside((1, 1)), True) def test_pointInside_false(self): component = self.getComponent_generic() - self.assertEqual( - component.pointInside((-1, -1)), - False - ) + self.assertEqual(component.pointInside((-1, -1)), False) # ---- # Hash @@ -814,41 +698,27 @@ def test_pointInside_false(self): def test_hash_object_self(self): component_one = self.getComponent_generic() - self.assertEqual( - hash(component_one), - hash(component_one) - ) + self.assertEqual(hash(component_one), hash(component_one)) def test_hash_object_other(self): component_one = self.getComponent_generic() component_two = self.getComponent_generic() - self.assertNotEqual( - hash(component_one), - hash(component_two) - ) + self.assertNotEqual(hash(component_one), hash(component_two)) def test_hash_object_self_variable_assignment(self): component_one = self.getComponent_generic() a = component_one - self.assertEqual( - hash(component_one), - hash(a) - ) + self.assertEqual(hash(component_one), hash(a)) def test_hash_object_other_variable_assignment(self): component_one = self.getComponent_generic() component_two = self.getComponent_generic() a = component_one - self.assertNotEqual( - hash(component_two), - hash(a) - ) + self.assertNotEqual(hash(component_two), hash(a)) def test_is_hashable(self): component_one = self.getComponent_generic() - self.assertTrue( - isinstance(component_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(component_one, collections.abc.Hashable)) # -------- # Equality @@ -856,36 +726,24 @@ def test_is_hashable(self): def test_object_equal_self(self): component_one = self.getComponent_generic() - self.assertEqual( - component_one, - component_one - ) + self.assertEqual(component_one, component_one) def test_object_not_equal_other(self): component_one = self.getComponent_generic() component_two = self.getComponent_generic() - self.assertNotEqual( - component_one, - component_two - ) + self.assertNotEqual(component_one, component_two) def test_object_equal_assigned_variable(self): component_one = self.getComponent_generic() a = component_one a.baseGlyph = "C" - self.assertEqual( - component_one, - a - ) + self.assertEqual(component_one, a) def test_object_not_equal_assigned_variable_other(self): component_one = self.getComponent_generic() component_two = self.getComponent_generic() a = component_one - self.assertNotEqual( - component_two, - a - ) + self.assertNotEqual(component_two, a) # --------- # Selection @@ -898,10 +756,7 @@ def test_selected_true(self): except NotImplementedError: return component.selected = True - self.assertEqual( - component.selected, - True - ) + self.assertEqual(component.selected, True) def test_selected_false(self): component = self.getComponent_generic() @@ -909,7 +764,4 @@ def test_selected_false(self): component.selected = False except NotImplementedError: return - self.assertEqual( - component.selected, - False - ) + self.assertEqual(component.selected, False) diff --git a/Lib/fontParts/test/test_contour.py b/Lib/fontParts/test/test_contour.py index d442916a..682e7e6d 100644 --- a/Lib/fontParts/test/test_contour.py +++ b/Lib/fontParts/test/test_contour.py @@ -4,7 +4,6 @@ class TestContour(unittest.TestCase): - def getContour_bounds(self): contour, _ = self.objectGenerator("contour") contour.appendPoint((0, 0), "line") @@ -75,10 +74,7 @@ def test_copyData(self): contour = self.getContour_bounds() contourOther, _ = self.objectGenerator("contour") contourOther.copyData(contour) - self.assertEqual( - contour.bounds, - contourOther.bounds - ) + self.assertEqual(contour.bounds, contourOther.bounds) # ------- # Parents @@ -213,27 +209,18 @@ def getContour_boundsExtrema(self): def test_bounds_get(self): contour = self.getContour_bounds() - self.assertEqual( - contour.bounds, - (0, 0, 100, 100) - ) + self.assertEqual(contour.bounds, (0, 0, 100, 100)) def test_bounds_set_float(self): contour = self.getContour_bounds() contour.moveBy((0.5, -0.5)) - self.assertEqual( - contour.bounds, - (0.5, -0.5, 100.5, 99.5) - ) + self.assertEqual(contour.bounds, (0.5, -0.5, 100.5, 99.5)) def test_bounds_point_not_at_extrema(self): contour = self.getContour_bounds() contour = self.getContour_boundsExtrema() bounds = tuple(int(round(i)) for i in contour.bounds) - self.assertEqual( - bounds, - (0, 0, 100, 100) - ) + self.assertEqual(bounds, (0, 0, 100, 100)) def test_invalid_bounds_set(self): contour = self.getContour_bounds() @@ -246,41 +233,27 @@ def test_invalid_bounds_set(self): def test_hash_object_self(self): contour_one = self.getContour_bounds() - self.assertEqual( - hash(contour_one), - hash(contour_one) - ) + self.assertEqual(hash(contour_one), hash(contour_one)) def test_hash_object_other(self): contour_one = self.getContour_bounds() contour_two = self.getContour_bounds() - self.assertNotEqual( - hash(contour_one), - hash(contour_two) - ) + self.assertNotEqual(hash(contour_one), hash(contour_two)) def test_hash_object_self_variable_assignment(self): contour_one = self.getContour_bounds() a = contour_one - self.assertEqual( - hash(contour_one), - hash(a) - ) + self.assertEqual(hash(contour_one), hash(a)) def test_hash_object_other_variable_assignment(self): contour_one = self.getContour_bounds() contour_two = self.getContour_bounds() a = contour_one - self.assertNotEqual( - hash(contour_two), - hash(a) - ) + self.assertNotEqual(hash(contour_two), hash(a)) def test_is_hashable(self): contour_one = self.getContour_bounds() - self.assertTrue( - isinstance(contour_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(contour_one, collections.abc.Hashable)) # -------- # Equality @@ -288,36 +261,24 @@ def test_is_hashable(self): def test_object_equal_self(self): contour_one = self.getContour_bounds() - self.assertEqual( - contour_one, - contour_one - ) + self.assertEqual(contour_one, contour_one) def test_object_not_equal_self(self): contour_one = self.getContour_bounds() contour_two = self.getContour_bounds() - self.assertNotEqual( - contour_one, - contour_two - ) + self.assertNotEqual(contour_one, contour_two) def test_object_equal_self_variable_assignment(self): contour_one = self.getContour_bounds() a = contour_one a.moveBy((0.5, -0.5)) - self.assertEqual( - contour_one, - a - ) + self.assertEqual(contour_one, a) def test_object_not_equal_self_variable_assignment(self): contour_one = self.getContour_bounds() contour_two = self.getContour_bounds() a = contour_one - self.assertNotEqual( - contour_two, - a - ) + self.assertNotEqual(contour_two, a) # --------- # Selection @@ -330,10 +291,7 @@ def test_selected_true(self): except NotImplementedError: return contour.selected = True - self.assertEqual( - contour.selected, - True - ) + self.assertEqual(contour.selected, True) def test_selected_false(self): contour = self.getContour_bounds() @@ -341,10 +299,7 @@ def test_selected_false(self): contour.selected = False except NotImplementedError: return - self.assertEqual( - contour.selected, - False - ) + self.assertEqual(contour.selected, False) def test_selectedSegments_default(self): contour = self.getContour_bounds() @@ -353,10 +308,7 @@ def test_selectedSegments_default(self): segment1.selected = False except NotImplementedError: return - self.assertEqual( - contour.selectedSegments, - () - ) + self.assertEqual(contour.selectedSegments, ()) def test_selectedSegments_setSubObject(self): contour = self.getContour_bounds() @@ -367,10 +319,7 @@ def test_selectedSegments_setSubObject(self): except NotImplementedError: return segment2.selected = True - self.assertEqual( - contour.selectedSegments == (segment2,), - True - ) + self.assertEqual(contour.selectedSegments == (segment2,), True) def test_selectedSegments_setFilledList(self): contour = self.getContour_bounds() @@ -381,10 +330,7 @@ def test_selectedSegments_setFilledList(self): except NotImplementedError: return contour.selectedSegments = [segment1, segment2] - self.assertEqual( - contour.selectedSegments, - (segment1, segment2) - ) + self.assertEqual(contour.selectedSegments, (segment1, segment2)) def test_selectedSegments_setEmptyList(self): contour = self.getContour_bounds() @@ -394,10 +340,7 @@ def test_selectedSegments_setEmptyList(self): except NotImplementedError: return contour.selectedSegments = [] - self.assertEqual( - contour.selectedSegments, - () - ) + self.assertEqual(contour.selectedSegments, ()) def test_selectedPoints_default(self): contour = self.getContour_bounds() @@ -406,10 +349,7 @@ def test_selectedPoints_default(self): point1.selected = False except NotImplementedError: return - self.assertEqual( - contour.selectedPoints, - () - ) + self.assertEqual(contour.selectedPoints, ()) def test_selectedPoints_setSubObject(self): contour = self.getContour_bounds() @@ -420,10 +360,7 @@ def test_selectedPoints_setSubObject(self): except NotImplementedError: return point2.selected = True - self.assertEqual( - contour.selectedPoints, - (point2,) - ) + self.assertEqual(contour.selectedPoints, (point2,)) def test_selectedPoints_setFilledList(self): contour = self.getContour_bounds() @@ -434,10 +371,7 @@ def test_selectedPoints_setFilledList(self): except NotImplementedError: return contour.selectedPoints = [point1, point2] - self.assertEqual( - contour.selectedPoints, - (point1, point2) - ) + self.assertEqual(contour.selectedPoints, (point1, point2)) def test_selectedPoints_setEmptyList(self): contour = self.getContour_bounds() @@ -447,10 +381,7 @@ def test_selectedPoints_setEmptyList(self): except NotImplementedError: return contour.selectedPoints = [] - self.assertEqual( - contour.selectedPoints, - () - ) + self.assertEqual(contour.selectedPoints, ()) def test_selectedBPoints_default(self): contour = self.getContour_bounds() @@ -459,10 +390,7 @@ def test_selectedBPoints_default(self): bPoint1.selected = False except NotImplementedError: return - self.assertEqual( - contour.selectedBPoints, - () - ) + self.assertEqual(contour.selectedBPoints, ()) def test_selectedBPoints_setSubObject(self): contour = self.getContour_bounds() @@ -473,10 +401,7 @@ def test_selectedBPoints_setSubObject(self): except NotImplementedError: return bPoint2.selected = True - self.assertEqual( - contour.selectedBPoints, - (bPoint2,) - ) + self.assertEqual(contour.selectedBPoints, (bPoint2,)) def test_selectedBPoints_setFilledList(self): contour = self.getContour_bounds() @@ -487,10 +412,7 @@ def test_selectedBPoints_setFilledList(self): except NotImplementedError: return contour.selectedBPoints = [bPoint1, bPoint2] - self.assertEqual( - contour.selectedBPoints, - (bPoint1, bPoint2) - ) + self.assertEqual(contour.selectedBPoints, (bPoint1, bPoint2)) def test_selectedBPoints_setEmptyList(self): contour = self.getContour_bounds() @@ -500,10 +422,7 @@ def test_selectedBPoints_setEmptyList(self): except NotImplementedError: return contour.selectedBPoints = [] - self.assertEqual( - contour.selectedBPoints, - () - ) + self.assertEqual(contour.selectedBPoints, ()) # -------- # Segments @@ -583,7 +502,7 @@ def test_segment_insert_open(self): contour.insertSegment(0, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (1, 1), (2, 2), (3, 3)] + [(0, 0), (1, 1), (2, 2), (3, 3)], ) # at index 1 contour, _ = self.objectGenerator("contour") @@ -593,7 +512,7 @@ def test_segment_insert_open(self): contour.insertSegment(1, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (2, 2), (1, 1), (3, 3)] + [(0, 0), (2, 2), (1, 1), (3, 3)], ) def test_segment_insert_curve_open(self): @@ -607,7 +526,7 @@ def test_segment_insert_curve_open(self): contour.insertSegment(0, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] + [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], ) # at index 1 contour, _ = self.objectGenerator("contour") @@ -619,7 +538,7 @@ def test_segment_insert_curve_open(self): contour.insertSegment(1, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (2, 2), (3, 3), (4, 4), (1, 1), (5, 5)] + [(0, 0), (2, 2), (3, 3), (4, 4), (1, 1), (5, 5)], ) def test_segment_insert_closed(self): @@ -631,7 +550,7 @@ def test_segment_insert_closed(self): contour.insertSegment(0, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (1, 1), (2, 2), (3, 3)] + [(0, 0), (1, 1), (2, 2), (3, 3)], ) # at index 1 contour, _ = self.objectGenerator("contour") @@ -641,7 +560,7 @@ def test_segment_insert_closed(self): contour.insertSegment(1, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (2, 2), (1, 1), (3, 3)] + [(0, 0), (2, 2), (1, 1), (3, 3)], ) def test_segment_insert_curve_closed(self): @@ -655,7 +574,7 @@ def test_segment_insert_curve_closed(self): contour.insertSegment(0, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)] + [(0, 0), (1, 1), (2, 2), (3, 3), (4, 4), (5, 5)], ) # at index 1 contour, _ = self.objectGenerator("contour") @@ -667,7 +586,7 @@ def test_segment_insert_curve_closed(self): contour.insertSegment(1, "line", [(1, 1)]) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(0, 0), (2, 2), (3, 3), (4, 4), (1, 1), (5, 5)] + [(0, 0), (2, 2), (3, 3), (4, 4), (1, 1), (5, 5)], ) def test_setStartSegment(self): @@ -702,5 +621,5 @@ def test_setStartPoint(self): contour.setStartPoint(2) self.assertEqual( [(point.x, point.y) for point in contour.points], - [(2, 2), (3, 3), (0, 0), (1, 1)] + [(2, 2), (3, 3), (0, 0), (1, 1)], ) diff --git a/Lib/fontParts/test/test_deprecated.py b/Lib/fontParts/test/test_deprecated.py index f5c403d3..fd45a75a 100644 --- a/Lib/fontParts/test/test_deprecated.py +++ b/Lib/fontParts/test/test_deprecated.py @@ -3,7 +3,6 @@ class TestDeprecated(unittest.TestCase): - # ---- # Font # ---- @@ -135,28 +134,19 @@ def test_anchor_deprecated__generateIdentifer(self): anchor, _ = self.objectGenerator("anchor") with self.assertWarnsRegex(DeprecationWarning, "Anchor._generateIdentifier()"): anchor._generateIdentifier() - self.assertEqual( - anchor._generateIdentifier(), - anchor._getIdentifier() - ) + self.assertEqual(anchor._generateIdentifier(), anchor._getIdentifier()) def test_anchor_deprecated_generateIdentifer(self): anchor, _ = self.objectGenerator("anchor") with self.assertWarnsRegex(DeprecationWarning, "Anchor.generateIdentifier()"): anchor.generateIdentifier() - self.assertEqual( - anchor.generateIdentifier(), - anchor.getIdentifier() - ) + self.assertEqual(anchor.generateIdentifier(), anchor.getIdentifier()) def test_anchor_deprecated_getParent(self): anchor = self.getAnchor() with self.assertWarnsRegex(DeprecationWarning, "Anchor.getParent()"): anchor.getParent() - self.assertEqual( - anchor.getParent(), - anchor.glyph - ) + self.assertEqual(anchor.getParent(), anchor.glyph) def test_anchor_deprecated_update(self): # As changed() is defined by the environment, only test if a Warning is issued. @@ -362,6 +352,7 @@ def test_feature_removed_round(self): def getImage_glyph(self): from fontParts.test.test_image import testImageData + glyph, _ = self.objectGenerator("glyph") glyph.addImage(data=testImageData) image = glyph.image @@ -426,12 +417,14 @@ def getKerning_generic(self): groups["public.kern1.X"] = ["A", "B", "C"] groups["public.kern2.X"] = ["A", "B", "C"] kerning = font.kerning - kerning.update({ - ("public.kern1.X", "public.kern2.X"): 100, - ("B", "public.kern2.X"): 101, - ("public.kern1.X", "B"): 102, - ("A", "A"): 103, - }) + kerning.update( + { + ("public.kern1.X", "public.kern2.X"): 100, + ("B", "public.kern2.X"): 101, + ("public.kern1.X", "B"): 102, + ("A", "A"): 103, + } + ) return kerning def test_kerning_removed_setParent(self): @@ -529,12 +522,14 @@ def test_kerning_removed_getParent(self): def test_groups_deprecated_getParent(self): font, _ = self.objectGenerator("font") groups = font.groups - groups.update({ - "group 1": ["A", "B", "C"], - "group 2": ["x", "y", "z"], - "group 3": [], - "group 4": ["A"] - }) + groups.update( + { + "group 1": ["A", "B", "C"], + "group 2": ["x", "y", "z"], + "group 3": [], + "group 4": ["A"], + } + ) with self.assertWarnsRegex(DeprecationWarning, "Groups.font"): groups.getParent() self.assertEqual(groups.getParent(), groups.font) @@ -548,12 +543,14 @@ def test_groups_deprecated_setChanged(self): def test_groups_removed_setParent(self): font, _ = self.objectGenerator("font") groups, _ = self.objectGenerator("groups") - groups.update({ - "group 1": ["A", "B", "C"], - "group 2": ["x", "y", "z"], - "group 3": [], - "group 4": ["A"] - }) + groups.update( + { + "group 1": ["A", "B", "C"], + "group 2": ["x", "y", "z"], + "group 3": [], + "group 4": ["A"], + } + ) with self.assertRaises(RemovedError): groups.setParent(font) @@ -564,12 +561,7 @@ def test_groups_removed_setParent(self): def test_lib_deprecated_getParent_font(self): font, _ = self.objectGenerator("font") lib = font.lib - lib.update({ - "key 1": ["A", "B", "C"], - "key 2": "x", - "key 3": [], - "key 4": 20 - }) + lib.update({"key 1": ["A", "B", "C"], "key 2": "x", "key 3": [], "key 4": 20}) with self.assertWarnsRegex(DeprecationWarning, "Lib.font"): lib.getParent() self.assertEqual(lib.getParent(), lib.font) @@ -578,12 +570,7 @@ def test_lib_deprecated_getParent_glyph(self): font, _ = self.objectGenerator("font") glyph = font.newGlyph("Test") lib = glyph.lib - lib.update({ - "key 1": ["A", "B", "C"], - "key 2": "x", - "key 3": [], - "key 4": 20 - }) + lib.update({"key 1": ["A", "B", "C"], "key 2": "x", "key 3": [], "key 4": 20}) with self.assertWarnsRegex(DeprecationWarning, "Lib.glyph"): lib.getParent() self.assertEqual(lib.getParent(), lib.glyph) @@ -597,24 +584,14 @@ def test_lib_deprecated_setChanged(self): def test_lib_removed_setParent_font(self): font, _ = self.objectGenerator("font") lib, _ = self.objectGenerator("lib") - lib.update({ - "key 1": ["A", "B", "C"], - "key 2": "x", - "key 3": [], - "key 4": 20 - }) + lib.update({"key 1": ["A", "B", "C"], "key 2": "x", "key 3": [], "key 4": 20}) with self.assertRaises(RemovedError): lib.setParent(font) def test_lib_removed_setParent_glyph(self): glyph, _ = self.objectGenerator("glyph") lib, _ = self.objectGenerator("lib") - lib.update({ - "key 1": ["A", "B", "C"], - "key 2": "x", - "key 3": [], - "key 4": 20 - }) + lib.update({"key 1": ["A", "B", "C"], "key 2": "x", "key 3": [], "key 4": 20}) with self.assertRaises(RemovedError): lib.setParent(glyph) @@ -1050,15 +1027,17 @@ def test_contour_deprecated_generateIdentifer(self): def test_contour_deprecated__generateIdentiferforPoint(self): contour = self.getContour_bounds() - with self.assertWarnsRegex(DeprecationWarning, - "Contour._generateIdentifierforPoint()"): + with self.assertWarnsRegex( + DeprecationWarning, "Contour._generateIdentifierforPoint()" + ): i = contour._generateIdentifierforPoint(contour[0][0]) self.assertEqual(i, contour._getIdentifierforPoint(contour[0][0])) def test_contour_deprecated_generateIdentiferForPoint(self): contour = self.getContour_bounds() - with self.assertWarnsRegex(DeprecationWarning, - "Contour.generateIdentifierforPoint()"): + with self.assertWarnsRegex( + DeprecationWarning, "Contour.generateIdentifierforPoint()" + ): i = contour.generateIdentifierforPoint(contour[0][0]) self.assertEqual(i, contour.getIdentifierForPoint(contour[0][0])) diff --git a/Lib/fontParts/test/test_features.py b/Lib/fontParts/test/test_features.py index 812b49a7..a2ac4450 100644 --- a/Lib/fontParts/test/test_features.py +++ b/Lib/fontParts/test/test_features.py @@ -3,7 +3,6 @@ class TestFeatures(unittest.TestCase): - def getFeatures_generic(self): features, _ = self.objectGenerator("features") features.text = "# test" @@ -35,18 +34,12 @@ def test_reprContents_noFont(self): def test_text_get(self): features = self.getFeatures_generic() - self.assertEqual( - features.text, - "# test" - ) + self.assertEqual(features.text, "# test") def test_text_valid_set(self): features = self.getFeatures_generic() features.text = "# foo" - self.assertEqual( - features.text, - "# foo" - ) + self.assertEqual(features.text, "# foo") def test_text_set_none(self): features = self.getFeatures_generic() @@ -67,10 +60,7 @@ def test_get_parent_font(self): features = font.features features.text = "# Test" self.assertIsNotNone(features.font) - self.assertEqual( - features.font, - font - ) + self.assertEqual(features.font, font) def test_get_parent_noFont(self): features = self.getFeatures_generic() @@ -81,10 +71,7 @@ def test_set_parent_font(self): features = self.getFeatures_generic() features.font = font self.assertIsNotNone(features.font) - self.assertEqual( - features.font, - font - ) + self.assertEqual(features.font, font) def test_set_parent_font_none(self): features = self.getFeatures_generic() @@ -105,10 +92,7 @@ def test_set_parent_font_exists(self): def test_hash(self): features = self.getFeatures_generic() - self.assertEqual( - isinstance(features, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(features, collections.abc.Hashable), True) # -------- # Equality @@ -116,33 +100,21 @@ def test_hash(self): def test_object_equal_self(self): features_one = self.getFeatures_generic() - self.assertEqual( - features_one, - features_one - ) + self.assertEqual(features_one, features_one) def test_object_not_equal_other(self): features_one = self.getFeatures_generic() features_two = self.getFeatures_generic() - self.assertNotEqual( - features_one, - features_two - ) + self.assertNotEqual(features_one, features_two) def test_object_equal_self_variable_assignment(self): features_one = self.getFeatures_generic() a = features_one a.text += "# testing" - self.assertEqual( - features_one, - a - ) + self.assertEqual(features_one, a) def test_object_not_equal_self_variable_assignment(self): features_one = self.getFeatures_generic() features_two = self.getFeatures_generic() a = features_one - self.assertNotEqual( - features_two, - a - ) + self.assertNotEqual(features_two, a) diff --git a/Lib/fontParts/test/test_font.py b/Lib/fontParts/test/test_font.py index 0cfb4dd3..94fef304 100644 --- a/Lib/fontParts/test/test_font.py +++ b/Lib/fontParts/test/test_font.py @@ -6,7 +6,6 @@ class TestFont(unittest.TestCase): - # ------ # Layers # ------ @@ -85,19 +84,13 @@ def test_glyphOrder(self): def test_len_initial(self): font = self.getFont_glyphs() - self.assertEqual( - len(font), - 4 - ) + self.assertEqual(len(font), 4) def test_len_two_layers(self): font = self.getFont_glyphs() layer = font.newLayer("test") layer.newGlyph("X") - self.assertEqual( - len(font), - 4 - ) + self.assertEqual(len(font), 4) # insert glyphs @@ -130,34 +123,34 @@ def test_flatKerning(self): # group, group kerning font.kerning["public.kern1.O", "public.kern2.O"] = -50 expected = { - ('O', 'O'): -50, - ('Ograve', 'O'): -50, - ('O', 'Ograve'): -50, - ('Ograve', 'Ograve'): -50, - ('A', 'V'): -100, - ('V', 'A'): -200 + ("O", "O"): -50, + ("Ograve", "O"): -50, + ("O", "Ograve"): -50, + ("Ograve", "Ograve"): -50, + ("A", "V"): -100, + ("V", "A"): -200, } self.assertEqual(font.getFlatKerning(), expected) # glyph, group exception font.kerning["O", "public.kern2.O"] = -30 expected = { - ('O', 'O'): -30, - ('Ograve', 'O'): -50, - ('O', 'Ograve'): -30, - ('Ograve', 'Ograve'): -50, - ('A', 'V'): -100, - ('V', 'A'): -200 + ("O", "O"): -30, + ("Ograve", "O"): -50, + ("O", "Ograve"): -30, + ("Ograve", "Ograve"): -50, + ("A", "V"): -100, + ("V", "A"): -200, } self.assertEqual(font.getFlatKerning(), expected) # glyph, glyph exception font.kerning["O", "Ograve"] = -70 expected = { - ('O', 'O'): -30, - ('Ograve', 'O'): -50, - ('O', 'Ograve'): -70, - ('Ograve', 'Ograve'): -50, - ('A', 'V'): -100, - ('V', 'A'): -200 + ("O", "O"): -30, + ("Ograve", "O"): -50, + ("O", "Ograve"): -70, + ("Ograve", "Ograve"): -50, + ("A", "V"): -100, + ("V", "A"): -200, } self.assertEqual(font.getFlatKerning(), expected) @@ -167,42 +160,27 @@ def test_flatKerning(self): def test_hash_same_object(self): font_one = self.getFont_glyphs() - self.assertEqual( - hash(font_one), - hash(font_one) - ) + self.assertEqual(hash(font_one), hash(font_one)) def test_hash_different_object(self): font_one = self.getFont_glyphs() font_two = self.getFont_glyphs() - self.assertNotEqual( - hash(font_one), - hash(font_two) - ) + self.assertNotEqual(hash(font_one), hash(font_two)) def test_hash_same_object_variable_assignment(self): font_one = self.getFont_glyphs() a = font_one - self.assertEqual( - hash(font_one), - hash(a) - ) + self.assertEqual(hash(font_one), hash(a)) def test_hash_different_object_variable_assignment(self): font_one = self.getFont_glyphs() font_two = self.getFont_glyphs() a = font_one - self.assertNotEqual( - hash(font_two), - hash(a) - ) + self.assertNotEqual(hash(font_two), hash(a)) def test_hash_is_hasbable(self): font_one = self.getFont_glyphs() - self.assertEqual( - isinstance(font_one, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(font_one, collections.abc.Hashable), True) # -------- # Equality @@ -210,36 +188,24 @@ def test_hash_is_hasbable(self): def test_object_equal_self(self): font_one = self.getFont_glyphs() - self.assertEqual( - font_one, - font_one - ) + self.assertEqual(font_one, font_one) def test_object_not_equal_other(self): font_one = self.getFont_glyphs() font_two = self.getFont_glyphs() - self.assertNotEqual( - font_one, - font_two - ) + self.assertNotEqual(font_one, font_two) def test_object_equal_self_variable_assignment(self): font_one = self.getFont_glyphs() a = font_one a.newGlyph("XYZ") - self.assertEqual( - font_one, - a - ) + self.assertEqual(font_one, a) def test_object_not_equal_other_variable_assignment(self): font_one = self.getFont_glyphs() font_two = self.getFont_glyphs() a = font_one - self.assertNotEqual( - font_two, - a - ) + self.assertNotEqual(font_two, a) # --------- # Selection @@ -254,10 +220,7 @@ def test_selected_true(self): except NotImplementedError: return font.selected = True - self.assertEqual( - font.selected, - True - ) + self.assertEqual(font.selected, True) def test_selected_false(self): font = self.getFont_glyphs() @@ -265,10 +228,7 @@ def test_selected_false(self): font.selected = False except NotImplementedError: return - self.assertEqual( - font.selected, - False - ) + self.assertEqual(font.selected, False) # Layers @@ -278,10 +238,7 @@ def test_selectedLayer_default(self): font.defaultLayer.selected = False except NotImplementedError: return - self.assertEqual( - font.selectedLayers, - () - ) + self.assertEqual(font.selectedLayers, ()) def test_selectedLayer_setSubObject(self): font = self.getFont_layers() @@ -293,10 +250,7 @@ def test_selectedLayer_setSubObject(self): layer2 = font.getLayer("layer B") layer1.selected = True layer2.selected = True - self.assertEqual( - font.selectedLayers, - (layer1, layer2) - ) + self.assertEqual(font.selectedLayers, (layer1, layer2)) def test_selectedLayer_setFilledList(self): font = self.getFont_layers() @@ -307,10 +261,7 @@ def test_selectedLayer_setFilledList(self): layer3 = font.getLayer("layer C") layer4 = font.getLayer("layer D") font.selectedLayers = [layer3, layer4] - self.assertEqual( - font.selectedLayers, - (layer3, layer4) - ) + self.assertEqual(font.selectedLayers, (layer3, layer4)) def test_selectedLayer_setEmptyList(self): font = self.getFont_layers() @@ -321,10 +272,7 @@ def test_selectedLayer_setEmptyList(self): layer1 = font.getLayer("layer A") layer1.selected = True font.selectedLayers = [] - self.assertEqual( - font.selectedLayers, - () - ) + self.assertEqual(font.selectedLayers, ()) # Glyphs @@ -334,10 +282,7 @@ def test_selectedGlyphs_default(self): font.defaultLayer.selected = False except NotImplementedError: return - self.assertEqual( - font.selectedGlyphs, - () - ) + self.assertEqual(font.selectedGlyphs, ()) def test_selectedGlyphs_setSubObject(self): font = self.getFont_glyphs() @@ -351,7 +296,7 @@ def test_selectedGlyphs_setSubObject(self): glyph2.selected = True self.assertEqual( tuple(sorted(font.selectedGlyphs, key=lambda glyph: glyph.name)), - (glyph1, glyph2) + (glyph1, glyph2), ) def test_selectedGlyphs_setFilledList(self): @@ -365,7 +310,7 @@ def test_selectedGlyphs_setFilledList(self): font.selectedGlyphs = [glyph3, glyph4] self.assertEqual( tuple(sorted(font.selectedGlyphs, key=lambda glyph: glyph.name)), - (glyph3, glyph4) + (glyph3, glyph4), ) def test_selectedGlyphs_setEmptyList(self): @@ -377,10 +322,7 @@ def test_selectedGlyphs_setEmptyList(self): glyph1 = font["A"] glyph1.selected = True font.selectedGlyphs = [] - self.assertEqual( - font.selectedGlyphs, - () - ) + self.assertEqual(font.selectedGlyphs, ()) # Glyph names @@ -390,10 +332,7 @@ def test_selectedGlyphNames_default(self): font.defaultLayer.selected = False except NotImplementedError: return - self.assertEqual( - font.selectedGlyphs, - () - ) + self.assertEqual(font.selectedGlyphs, ()) def test_selectedGlyphNames_setSubObject(self): font = self.getFont_glyphs() @@ -405,10 +344,7 @@ def test_selectedGlyphNames_setSubObject(self): glyph2 = font["B"] glyph1.selected = True glyph2.selected = True - self.assertEqual( - tuple(sorted(font.selectedGlyphNames)), - ("A", "B") - ) + self.assertEqual(tuple(sorted(font.selectedGlyphNames)), ("A", "B")) def test_selectedGlyphNames_setFilledList(self): font = self.getFont_glyphs() @@ -417,10 +353,7 @@ def test_selectedGlyphNames_setFilledList(self): except NotImplementedError: return font.selectedGlyphNames = ["C", "D"] - self.assertEqual( - tuple(sorted(font.selectedGlyphNames)), - ("C", "D") - ) + self.assertEqual(tuple(sorted(font.selectedGlyphNames)), ("C", "D")) def test_selectedGlyphNames_setEmptyList(self): font = self.getFont_glyphs() @@ -431,10 +364,7 @@ def test_selectedGlyphNames_setEmptyList(self): glyph1 = font["A"] glyph1.selected = True font.selectedGlyphNames = [] - self.assertEqual( - font.selectedGlyphNames, - () - ) + self.assertEqual(font.selectedGlyphNames, ()) # Guidelines @@ -445,10 +375,7 @@ def test_selectedGuidelines_default(self): guideline1.selected = False except NotImplementedError: return - self.assertEqual( - font.selectedGuidelines, - () - ) + self.assertEqual(font.selectedGuidelines, ()) def test_selectedGuidelines_setSubObject(self): font = self.getFont_guidelines() @@ -459,10 +386,7 @@ def test_selectedGuidelines_setSubObject(self): except NotImplementedError: return guideline2.selected = True - self.assertEqual( - font.selectedGuidelines, - (guideline2,) - ) + self.assertEqual(font.selectedGuidelines, (guideline2,)) def test_selectedGuidelines_setFilledList(self): font = self.getFont_guidelines() @@ -473,10 +397,7 @@ def test_selectedGuidelines_setFilledList(self): except NotImplementedError: return font.selectedGuidelines = [guideline1, guideline2] - self.assertEqual( - font.selectedGuidelines, - (guideline1, guideline2) - ) + self.assertEqual(font.selectedGuidelines, (guideline1, guideline2)) def test_selectedGuidelines_setEmptyList(self): font = self.getFont_guidelines() @@ -486,10 +407,7 @@ def test_selectedGuidelines_setEmptyList(self): except NotImplementedError: return font.selectedGuidelines = [] - self.assertEqual( - font.selectedGuidelines, - () - ) + self.assertEqual(font.selectedGuidelines, ()) # save @@ -514,21 +432,28 @@ def _save(self, testCallback, **kwargs): def test_save(self): def testCases(path): self.assertTrue(os.path.exists(path) and os.path.isdir(path)) + self._save(testCases) def test_save_formatVersion(self): from fontTools.ufoLib import UFOReader - for version in [2, 3]: # fails on formatVersion 1 (but maybe we should not worry about it...) + for version in [ + 2, + 3, + ]: # fails on formatVersion 1 (but maybe we should not worry about it...) + def testCases(path): reader = UFOReader(path) self.assertEqual(reader.formatVersion, version) + self._save(testCases, formatVersion=version) def test_save_fileStructure(self): from fontTools.ufoLib import UFOReader, UFOFileStructure for fileStructure in [None, "package", "zip"]: + def testCases(path): reader = UFOReader(path) expectedFileStructure = fileStructure @@ -537,6 +462,7 @@ def testCases(path): else: expectedFileStructure = UFOFileStructure(fileStructure) self.assertEqual(reader.fileStructure, expectedFileStructure) + self._save(testCases, fileStructure=fileStructure) # copy @@ -544,29 +470,17 @@ def testCases(path): def test_copy(self): font = self.getFont_glyphs() copy = font.copy() - self.assertEqual( - font.keys(), - copy.keys() - ) + self.assertEqual(font.keys(), copy.keys()) font = self.getFont_glyphs() font.defaultLayer.name = "hello" copy = font.copy() - self.assertEqual( - font.keys(), - copy.keys() - ) - self.assertEqual( - font.defaultLayerName, - copy.defaultLayerName - ) + self.assertEqual(font.keys(), copy.keys()) + self.assertEqual(font.defaultLayerName, copy.defaultLayerName) font = self.getFont_guidelines() copy = font.copy() - self.assertEqual( - copy.selectedGuidelines, - font.selectedGuidelines - ) + self.assertEqual(copy.selectedGuidelines, font.selectedGuidelines) # ------------- # Interpolation @@ -578,12 +492,8 @@ def test_interpolate_global_guidelines(self): font_min.appendGuideline(position=(0, 0), angle=0) font_max, _ = self.objectGenerator("font") font_max.appendGuideline(position=(200, 200), angle=0) - interpolated_font.info.interpolate(0.5, font_min.info, font_max.info, round=True) - self.assertEqual( - len(interpolated_font.guidelines), - 1 + interpolated_font.info.interpolate( + 0.5, font_min.info, font_max.info, round=True ) - self.assertEqual( - interpolated_font.guidelines[0].position, - (100, 100) - ) \ No newline at end of file + self.assertEqual(len(interpolated_font.guidelines), 1) + self.assertEqual(interpolated_font.guidelines[0].position, (100, 100)) diff --git a/Lib/fontParts/test/test_fuzzyNumber.py b/Lib/fontParts/test/test_fuzzyNumber.py index 40b3b7d6..c5e50a01 100644 --- a/Lib/fontParts/test/test_fuzzyNumber.py +++ b/Lib/fontParts/test/test_fuzzyNumber.py @@ -3,17 +3,14 @@ class TestFuzzyNumber(unittest.TestCase): - def __init__(self, methodName): unittest.TestCase.__init__(self, methodName) def test_init(self): fuzzyNumber1 = FuzzyNumber(value=0, threshold=1) fuzzyNumber2 = FuzzyNumber(2, 3) - self.assertEqual([fuzzyNumber1.value, fuzzyNumber1.threshold], - [0, 1]) - self.assertEqual([fuzzyNumber2.value, fuzzyNumber2.threshold], - [2, 3]) + self.assertEqual([fuzzyNumber1.value, fuzzyNumber1.threshold], [0, 1]) + self.assertEqual([fuzzyNumber2.value, fuzzyNumber2.threshold], [2, 3]) def test_repr(self): fuzzyNumber = FuzzyNumber(0, 1) @@ -29,28 +26,28 @@ def test_comparison(self): fuzzyNumber2 = FuzzyNumber(value=0.999999, threshold=1) self.assertEqual( repr(sorted([fuzzyNumber1, fuzzyNumber2])), - "[[0.000000 1.000000], [0.999999 1.000000]]" + "[[0.000000 1.000000], [0.999999 1.000000]]", ) self.assertFalse(fuzzyNumber1 < fuzzyNumber2) fuzzyNumber2 = FuzzyNumber(value=1, threshold=1) self.assertEqual( repr(sorted([fuzzyNumber1, fuzzyNumber2])), - "[[0.000000 1.000000], [1.000000 1.000000]]" + "[[0.000000 1.000000], [1.000000 1.000000]]", ) self.assertTrue(fuzzyNumber1 < fuzzyNumber2) fuzzyNumber2 = FuzzyNumber(value=-0.999999, threshold=1) self.assertEqual( repr(sorted([fuzzyNumber1, fuzzyNumber2])), - "[[0.000000 1.000000], [-0.999999 1.000000]]" + "[[0.000000 1.000000], [-0.999999 1.000000]]", ) self.assertFalse(fuzzyNumber1 > fuzzyNumber2) fuzzyNumber2 = FuzzyNumber(value=-1, threshold=1) self.assertEqual( repr(sorted([fuzzyNumber1, fuzzyNumber2])), - "[[-1.000000 1.000000], [0.000000 1.000000]]" + "[[-1.000000 1.000000], [0.000000 1.000000]]", ) self.assertTrue(fuzzyNumber1 > fuzzyNumber2) @@ -62,6 +59,5 @@ def test_comparison(self): fuzzyNumber2 = FuzzyNumber(value=0.999999, threshold=1) self.assertEqual( repr(sorted([(fuzzyNumber1, 20), (fuzzyNumber2, 10)])), - "[([0.999999 1.000000], 10), ([0.000000 1.000000], 20)]" + "[([0.999999 1.000000], 10), ([0.000000 1.000000], 20)]", ) - diff --git a/Lib/fontParts/test/test_glyph.py b/Lib/fontParts/test/test_glyph.py index 20d01ae6..0ee492d8 100644 --- a/Lib/fontParts/test/test_glyph.py +++ b/Lib/fontParts/test/test_glyph.py @@ -5,7 +5,6 @@ class TestGlyph(unittest.TestCase): - def getGlyph_generic(self): glyph, _ = self.objectGenerator("glyph") glyph.name = "Test Glyph 1" @@ -49,10 +48,7 @@ def test_get_layer(self): font = self.get_generic_object("font") layer = font.layers[0] glyph = layer.newGlyph("A") - self.assertEqual( - glyph.layer, - layer - ) + self.assertEqual(glyph.layer, layer) def test_get_layer_orphan_glyph(self): glyph = self.get_generic_object("glyph") @@ -61,10 +57,7 @@ def test_get_layer_orphan_glyph(self): def test_get_font(self): font = self.get_generic_object("font") glyph = font.newGlyph("A") - self.assertEqual( - glyph.font, - font - ) + self.assertEqual(glyph.font, font) def test_get_font_orphan_glyph(self): glyph = self.get_generic_object("glyph") @@ -76,32 +69,24 @@ def test_get_font_orphan_glyph(self): def test_get_name(self): glyph = self.getGlyph_generic() - self.assertEqual( - glyph.name, - "Test Glyph 1" - ) + self.assertEqual(glyph.name, "Test Glyph 1") def test_get_name_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.name - ) + self.assertIsNone(glyph.name) def test_set_name_valid(self): glyph = self.getGlyph_generic() name = "Test Glyph 1" # the name is intentionally the same glyph.name = name - self.assertEqual( - glyph.name, - name - ) + self.assertEqual(glyph.name, name) def test_set_name_invalid(self): invalid_names = ( ("", ValueError), ("A", ValueError), # a glyph with this name already exists (3, TypeError), - (None, TypeError) + (None, TypeError), ) font = self.get_generic_object("font") font.newGlyph("A") @@ -112,52 +97,34 @@ def test_set_name_invalid(self): def test_get_unicode(self): glyph = self.getGlyph_generic() - self.assertEqual( - glyph.unicode, - 88 - ) + self.assertEqual(glyph.unicode, 88) def test_get_unicode_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.unicode - ) + self.assertIsNone(glyph.unicode) def test_set_unicode_valid(self): - valid_uni_values = (100, None, 0x6D, '6D') + valid_uni_values = (100, None, 0x6D, "6D") for value in valid_uni_values: glyph = self.get_generic_object("glyph") glyph.unicode = value result = int(value, 16) if isinstance(value, str) else value - self.assertEqual( - glyph.unicode, - result - ) + self.assertEqual(glyph.unicode, result) def test_set_unicode_value(self): glyph = self.get_generic_object("glyph") glyph.unicodes = (10, 20) glyph.unicode = 20 - self.assertEqual( - glyph.unicodes, - (20,) - ) + self.assertEqual(glyph.unicodes, (20,)) def test_set_unicode_value_none(self): glyph = self.get_generic_object("glyph") glyph.unicodes = (10, 20) glyph.unicode = None - self.assertEqual( - glyph.unicodes, - () - ) + self.assertEqual(glyph.unicodes, ()) def test_set_unicode_invalid(self): - invalid_uni_values = ( - ('GG', ValueError), - (True, TypeError), - ([], TypeError) - ) + invalid_uni_values = (("GG", ValueError), (True, TypeError), ([], TypeError)) glyph = self.get_generic_object("glyph") for value, err in invalid_uni_values: with self.assertRaises(err): @@ -165,34 +132,21 @@ def test_set_unicode_invalid(self): def test_get_unicodes(self): glyph = self.getGlyph_generic() - self.assertEqual( - glyph.unicodes, - (88,) - ) + self.assertEqual(glyph.unicodes, (88,)) def test_get_unicodes_not_set(self): glyph = self.get_generic_object("glyph") - self.assertEqual( - glyph.unicodes, - () - ) + self.assertEqual(glyph.unicodes, ()) def test_set_unicodes_valid(self): valid_uni_values = ([100, 200], [], (300,), ()) for values in valid_uni_values: glyph = self.get_generic_object("glyph") glyph.unicodes = values - self.assertEqual( - glyph.unicodes, - tuple(values) - ) + self.assertEqual(glyph.unicodes, tuple(values)) def test_set_unicodes_invalid(self): - invalid_uni_values = ( - ('GG', ValueError), - (True, TypeError), - (30, TypeError) - ) + invalid_uni_values = (("GG", ValueError), (True, TypeError), (30, TypeError)) glyph = self.get_generic_object("glyph") for value, err in invalid_uni_values: with self.assertRaises(err): @@ -213,27 +167,19 @@ def test_set_unicodes_duplicates(self): def test_get_leftMargin_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.leftMargin - ) + self.assertIsNone(glyph.leftMargin) def test_get_rightMargin_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.rightMargin - ) + self.assertIsNone(glyph.rightMargin) def test_get_bottomMargin_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.bottomMargin - ) + self.assertIsNone(glyph.bottomMargin) def test_get_topMargin_not_set(self): glyph = self.get_generic_object("glyph") - self.assertIsNone( - glyph.topMargin - ) + self.assertIsNone(glyph.topMargin) # ------- # Queries @@ -241,10 +187,7 @@ def test_get_topMargin_not_set(self): def test_get_bounds(self): glyph = self.getGlyph_generic() - self.assertEqual( - glyph.bounds, - (100, -10, 200, 100) - ) + self.assertEqual(glyph.bounds, (100, -10, 200, 100)) # ------ # Layers @@ -255,40 +198,28 @@ def test_get_layers(self): glyph = font.newGlyph("A") layers = glyph.layers self.assertEqual(len(layers), 1) - self.assertEqual( - glyph.layer.name, - font.defaultLayerName - ) + self.assertEqual(glyph.layer.name, font.defaultLayerName) self.assertEqual( layers[0], - glyph # a glyph layer is really just a glyph - ) - self.assertEqual( - layers[0].name, - 'A' + glyph, # a glyph layer is really just a glyph ) + self.assertEqual(layers[0].name, "A") def test_get_layers_orphan_glyph(self): glyph = self.getGlyph_generic() - self.assertEqual( - glyph.layers, - () - ) + self.assertEqual(glyph.layers, ()) def test_getLayer_valid(self): font = self.get_generic_object("font") glyph = font.newGlyph("B") - self.assertEqual( - glyph.getLayer(font.defaultLayerName).name, - 'B' - ) + self.assertEqual(glyph.getLayer(font.defaultLayerName).name, "B") def test_getLayer_valid_not_found(self): font = self.get_generic_object("font") glyph = font.newGlyph("B") with self.assertRaises(ValueError): # No layer named 'layer_name' in glyph 'B' - glyph.getLayer('layer_name') + glyph.getLayer("layer_name") def test_getLayer_invalid(self): font = self.get_generic_object("font") @@ -301,7 +232,7 @@ def test_getLayer_invalid(self): glyph.getLayer(0) with self.assertRaises(ValueError): # Layer names must be at least one character long - glyph.getLayer('') + glyph.getLayer("") def test_newLayer_valid(self): font = self.get_generic_object("font") @@ -309,7 +240,7 @@ def test_newLayer_valid(self): self.assertEqual(len(glyph.layers), 1) layer = glyph.newLayer("background") self.assertEqual(len(glyph.layers), 2) - self.assertEqual(layer.name, 'C') + self.assertEqual(layer.name, "C") def test_newLayer_valid_already_exists(self): font = self.get_generic_object("font") @@ -329,7 +260,7 @@ def test_newLayer_invalid(self): glyph.newLayer(0) with self.assertRaises(ValueError): # Layer names must be at least one character long - glyph.newLayer('') + glyph.newLayer("") def test_removeLayer_valid_type_string(self): font = self.get_generic_object("font") @@ -350,7 +281,7 @@ def test_removeLayer_valid_not_found_type_string(self): glyph = font.newGlyph("D") with self.assertRaises(ValueError): # No layer named 'layer_name' in glyph 'D' - glyph.removeLayer('layer_name') + glyph.removeLayer("layer_name") def test_removeLayer_invalid(self): font = self.get_generic_object("font") @@ -361,7 +292,7 @@ def test_removeLayer_invalid(self): glyph.removeLayer(0) with self.assertRaises(ValueError): # Layer names must be at least one character long - glyph.removeLayer('') + glyph.removeLayer("") # ------ # Global @@ -374,8 +305,13 @@ def test_clear(self): self.assertEqual(len(glyph.components), 1) self.assertEqual(len(glyph.anchors), 2) self.assertEqual(len(glyph.guidelines), 2) - glyph.clear(contours=False, components=False, anchors=False, - guidelines=False, image=False) + glyph.clear( + contours=False, + components=False, + anchors=False, + guidelines=False, + image=False, + ) glyph.clear() self.assertEqual(len(glyph), 0) self.assertEqual(len(glyph.components), 0) @@ -580,8 +516,7 @@ def test_autoContourOrder_bboxsurface(self): glyph.autoContourOrder() self.assertTrue( - glyph.contours[0].points[0].y == 0 - and glyph.contours[1].points[0].y == 50 + glyph.contours[0].points[0].y == 0 and glyph.contours[1].points[0].y == 50 ) # ---------- @@ -789,10 +724,7 @@ def test_addImage(self): font = self.get_generic_object("font") glyph = font.newGlyph("glyphWithImage") image = glyph.addImage(data=testImageData) - self.assertEqual( - image.data, - testImageData - ) + self.assertEqual(image.data, testImageData) # ---- # Hash @@ -801,43 +733,29 @@ def test_addImage(self): def test_hash_object_self(self): glyph_one = self.getGlyph_generic() glyph_one.name = "Test" - self.assertEqual( - hash(glyph_one), - hash(glyph_one) - ) + self.assertEqual(hash(glyph_one), hash(glyph_one)) def test_hash_object_other(self): glyph_one = self.getGlyph_generic() glyph_two = self.getGlyph_generic() glyph_one.name = "Test" glyph_two.name = "Test" - self.assertNotEqual( - hash(glyph_one), - hash(glyph_two) - ) + self.assertNotEqual(hash(glyph_one), hash(glyph_two)) def test_hash_object_self_variable_assignment(self): glyph_one = self.getGlyph_generic() a = glyph_one - self.assertEqual( - hash(glyph_one), - hash(a) - ) + self.assertEqual(hash(glyph_one), hash(a)) def test_hash_object_other_variable_assignment(self): glyph_one = self.getGlyph_generic() glyph_two = self.getGlyph_generic() a = glyph_one - self.assertNotEqual( - hash(glyph_two), - hash(a) - ) + self.assertNotEqual(hash(glyph_two), hash(a)) def test_is_hashable(self): glyph_one = self.getGlyph_generic() - self.assertTrue( - isinstance(glyph_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(glyph_one, collections.abc.Hashable)) # -------- # Equality @@ -846,46 +764,31 @@ def test_is_hashable(self): def test_object_equal_self(self): glyph_one = self.getGlyph_generic() glyph_one.name = "Test" - self.assertEqual( - glyph_one, - glyph_one - ) + self.assertEqual(glyph_one, glyph_one) def test_object_not_equal_other(self): glyph_one = self.getGlyph_generic() glyph_two = self.getGlyph_generic() - self.assertNotEqual( - glyph_one, - glyph_two - ) + self.assertNotEqual(glyph_one, glyph_two) def test_object_not_equal_other_name_same(self): glyph_one = self.getGlyph_generic() glyph_two = self.getGlyph_generic() glyph_one.name = "Test" glyph_two.name = "Test" - self.assertNotEqual( - glyph_one, - glyph_two - ) + self.assertNotEqual(glyph_one, glyph_two) def test_object_equal_variable_assignment(self): glyph_one = self.getGlyph_generic() a = glyph_one a.name = "Other" - self.assertEqual( - glyph_one, - a - ) + self.assertEqual(glyph_one, a) def test_object_not_equal_variable_assignment(self): glyph_one = self.getGlyph_generic() glyph_two = self.getGlyph_generic() a = glyph_one - self.assertNotEqual( - glyph_two, - a - ) + self.assertNotEqual(glyph_two, a) # --------- # Selection @@ -898,9 +801,7 @@ def test_selected_true(self): except NotImplementedError: return glyph.selected = True - self.assertTrue( - glyph.selected - ) + self.assertTrue(glyph.selected) def test_not_selected_false(self): glyph = self.getGlyph_generic() @@ -908,9 +809,7 @@ def test_not_selected_false(self): glyph.selected = False except NotImplementedError: return - self.assertFalse( - glyph.selected - ) + self.assertFalse(glyph.selected) # Contours @@ -921,10 +820,7 @@ def test_selectedContours_default(self): contour1.selected = False except NotImplementedError: return - self.assertEqual( - glyph.selectedContours, - () - ) + self.assertEqual(glyph.selectedContours, ()) def test_selectedContours_setSubObject(self): glyph = self.getGlyph_generic() @@ -935,10 +831,7 @@ def test_selectedContours_setSubObject(self): except NotImplementedError: return contour2.selected = True - self.assertEqual( - glyph.selectedContours, - (contour2,) - ) + self.assertEqual(glyph.selectedContours, (contour2,)) def test_selectedContours_setFilledList(self): glyph = self.getGlyph_generic() @@ -949,10 +842,7 @@ def test_selectedContours_setFilledList(self): except NotImplementedError: return glyph.selectedContours = [contour1, contour2] - self.assertEqual( - glyph.selectedContours, - (contour1, contour2) - ) + self.assertEqual(glyph.selectedContours, (contour1, contour2)) def test_selectedContours_setEmptyList(self): glyph = self.getGlyph_generic() @@ -962,10 +852,7 @@ def test_selectedContours_setEmptyList(self): except NotImplementedError: return glyph.selectedContours = [] - self.assertEqual( - glyph.selectedContours, - () - ) + self.assertEqual(glyph.selectedContours, ()) # Components def test_selectedComponents_default(self): @@ -976,10 +863,7 @@ def test_selectedComponents_default(self): component1.selected = False except NotImplementedError: return - self.assertEqual( - glyph.selectedComponents, - () - ) + self.assertEqual(glyph.selectedComponents, ()) def test_selectedComponents_setSubObject(self): glyph = self.getGlyph_generic() @@ -992,10 +876,7 @@ def test_selectedComponents_setSubObject(self): except NotImplementedError: return component2.selected = True - self.assertEqual( - glyph.selectedComponents, - (component2,) - ) + self.assertEqual(glyph.selectedComponents, (component2,)) def test_selectedComponents_setFilledList(self): glyph = self.getGlyph_generic() @@ -1008,10 +889,7 @@ def test_selectedComponents_setFilledList(self): except NotImplementedError: return glyph.selectedComponents = [component1, component2] - self.assertEqual( - glyph.selectedComponents, - (component1, component2) - ) + self.assertEqual(glyph.selectedComponents, (component1, component2)) def test_selectedComponents_setEmptyList(self): glyph = self.getGlyph_generic() @@ -1022,10 +900,7 @@ def test_selectedComponents_setEmptyList(self): except NotImplementedError: return glyph.selectedComponents = [] - self.assertEqual( - glyph.selectedComponents, - () - ) + self.assertEqual(glyph.selectedComponents, ()) # Anchors @@ -1036,10 +911,7 @@ def test_selectedAnchors_default(self): anchor1.selected = False except NotImplementedError: return - self.assertEqual( - glyph.selectedAnchors, - () - ) + self.assertEqual(glyph.selectedAnchors, ()) def test_selectedAnchors_setSubObject(self): glyph = self.getGlyph_generic() @@ -1050,10 +922,7 @@ def test_selectedAnchors_setSubObject(self): except NotImplementedError: return anchor2.selected = True - self.assertEqual( - glyph.selectedAnchors, - (anchor2,) - ) + self.assertEqual(glyph.selectedAnchors, (anchor2,)) def test_selectedAnchors_setFilledList(self): glyph = self.getGlyph_generic() @@ -1064,10 +933,7 @@ def test_selectedAnchors_setFilledList(self): except NotImplementedError: return glyph.selectedAnchors = [anchor1, anchor2] - self.assertEqual( - glyph.selectedAnchors, - (anchor1, anchor2) - ) + self.assertEqual(glyph.selectedAnchors, (anchor1, anchor2)) def test_selectedAnchors_setEmptyList(self): glyph = self.getGlyph_generic() @@ -1077,10 +943,7 @@ def test_selectedAnchors_setEmptyList(self): except NotImplementedError: return glyph.selectedAnchors = [] - self.assertEqual( - glyph.selectedAnchors, - () - ) + self.assertEqual(glyph.selectedAnchors, ()) # Guidelines @@ -1091,10 +954,7 @@ def test_selectedGuidelines_default(self): guideline1.selected = False except NotImplementedError: return - self.assertEqual( - glyph.selectedGuidelines, - () - ) + self.assertEqual(glyph.selectedGuidelines, ()) def test_selectedGuidelines_setSubObject(self): glyph = self.getGlyph_generic() @@ -1105,10 +965,7 @@ def test_selectedGuidelines_setSubObject(self): except NotImplementedError: return guideline2.selected = True - self.assertEqual( - glyph.selectedGuidelines, - (guideline2,) - ) + self.assertEqual(glyph.selectedGuidelines, (guideline2,)) def test_selectedGuidelines_setFilledList(self): glyph = self.getGlyph_generic() @@ -1119,10 +976,7 @@ def test_selectedGuidelines_setFilledList(self): except NotImplementedError: return glyph.selectedGuidelines = [guideline1, guideline2] - self.assertEqual( - glyph.selectedGuidelines, - (guideline1, guideline2) - ) + self.assertEqual(glyph.selectedGuidelines, (guideline1, guideline2)) def test_selectedGuidelines_setEmptyList(self): glyph = self.getGlyph_generic() @@ -1132,10 +986,7 @@ def test_selectedGuidelines_setEmptyList(self): except NotImplementedError: return glyph.selectedGuidelines = [] - self.assertEqual( - glyph.selectedGuidelines, - () - ) + self.assertEqual(glyph.selectedGuidelines, ()) # ------------- # Compatibility @@ -1301,10 +1152,7 @@ def test_interpolate_glyphWidth_without_rounding(self): glyph_min.width = 1000 glyph_max.width = 2000 interpolated.interpolate(0.5154, glyph_min, glyph_max, round=False) - self.assertEqual( - interpolated.width, - 1515.4 - ) + self.assertEqual(interpolated.width, 1515.4) def test_interpolate_glyphWidth_with_rounding(self): interpolated, _ = self.objectGenerator("glyph") @@ -1313,10 +1161,7 @@ def test_interpolate_glyphWidth_with_rounding(self): glyph_min.width = 1000 glyph_max.width = 2000 interpolated.interpolate(0.5154, glyph_min, glyph_max, round=True) - self.assertEqual( - interpolated.width, - 1515 - ) + self.assertEqual(interpolated.width, 1515) # --------------- # Transformations @@ -1325,15 +1170,9 @@ def test_interpolate_glyphWidth_with_rounding(self): def test_moveBy_only_contours(self): glyph = self.getGlyph_generic() glyph.moveBy((100, 0)) - self.assertEqual( - glyph.bounds[0], - 200 - ) + self.assertEqual(glyph.bounds[0], 200) glyph.moveBy((0, 250)) - self.assertEqual( - glyph.bounds[1], - 240 - ) + self.assertEqual(glyph.bounds[1], 240) # --- # API @@ -1362,38 +1201,44 @@ def test_removeOverlap(self): def test_generator(test_name, metric, value): - if '_invalid_' in test_name: + if "_invalid_" in test_name: + def test(self): glyph = self.getGlyph_generic() with self.assertRaises(TypeError): setattr(glyph, metric, value) else: + def test(self): glyph = self.getGlyph_generic() - if '_set_' in test_name: + if "_set_" in test_name: setattr(glyph, metric, value) - self.assertEqual( - getattr(glyph, metric), - value - ) + self.assertEqual(getattr(glyph, metric), value) + return test -t_names = ('_get', '_set_valid_positive', '_set_valid_negative', - '_set_valid_zero', '_set_valid_float', '_set_invalid_string', - '_set_invalid_none') -invalid = ('abc', None) +t_names = ( + "_get", + "_set_valid_positive", + "_set_valid_negative", + "_set_valid_zero", + "_set_valid_float", + "_set_invalid_string", + "_set_invalid_none", +) +invalid = ("abc", None) metrics = { - 'width': (250, 300, -485, 0, 101.5) + invalid, - 'height': (750, 800, -10, 0, 801.5) + invalid, - 'leftMargin': (100, 200, -15, 0, 201.5) + invalid, - 'rightMargin': (50, 80, -20, 0, 81.5) + invalid, - 'bottomMargin': (-10, 150, -35, 0, 151.5) + invalid, - 'topMargin': (650, 750, -250, 0, 751.5) + invalid, + "width": (250, 300, -485, 0, 101.5) + invalid, + "height": (750, 800, -10, 0, 801.5) + invalid, + "leftMargin": (100, 200, -15, 0, 201.5) + invalid, + "rightMargin": (50, 80, -20, 0, 81.5) + invalid, + "bottomMargin": (-10, 150, -35, 0, 151.5) + invalid, + "topMargin": (650, 750, -250, 0, 751.5) + invalid, } for i, t_name_suffix in enumerate(t_names): for metric_name, values in metrics.items(): - test_name = 'test_{}{}'.format(metric_name, t_name_suffix) + test_name = "test_{}{}".format(metric_name, t_name_suffix) test = test_generator(test_name, metric_name, values[i]) setattr(TestGlyph, test_name, test) diff --git a/Lib/fontParts/test/test_groups.py b/Lib/fontParts/test/test_groups.py index a2f1e340..0fe9e2ba 100644 --- a/Lib/fontParts/test/test_groups.py +++ b/Lib/fontParts/test/test_groups.py @@ -3,15 +3,16 @@ class TestGroups(unittest.TestCase): - def getGroups_generic(self): groups, _ = self.objectGenerator("groups") - groups.update({ - "group 1": ["A", "B", "C"], - "group 2": ["x", "y", "z"], - "group 3": [], - "group 4": ["A"] - }) + groups.update( + { + "group 1": ["A", "B", "C"], + "group 2": ["x", "y", "z"], + "group 3": [], + "group 4": ["A"], + } + ) return groups # ---- @@ -36,7 +37,6 @@ def test_reprContents_noFont(self): self.assertIsInstance(value, list) self.assertEqual(value, []) - # ------- # Parents # ------- @@ -45,10 +45,7 @@ def test_get_parent_font(self): font, _ = self.objectGenerator("font") groups = font.groups self.assertIsNotNone(groups.font) - self.assertEqual( - groups.font, - font - ) + self.assertEqual(groups.font, font) def test_get_parent_font_none(self): groups, _ = self.objectGenerator("groups") @@ -59,10 +56,7 @@ def test_set_parent_font(self): groups, _ = self.objectGenerator("groups") groups.font = font self.assertIsNotNone(groups.font) - self.assertEqual( - groups.font, - font - ) + self.assertEqual(groups.font, font) def test_set_parent_font_none(self): groups, _ = self.objectGenerator("groups") @@ -85,36 +79,22 @@ def test_set_parent_differentFont(self): def test_len_initial(self): groups = self.getGroups_generic() - self.assertEqual( - len(groups), - 4 - ) + self.assertEqual(len(groups), 4) def test_len_clear(self): groups = self.getGroups_generic() groups.clear() - self.assertEqual( - len(groups), - 0 - ) + self.assertEqual(len(groups), 0) def test_len_add(self): groups = self.getGroups_generic() - groups['group 5'] = ["D","E","F"] - self.assertEqual( - len(groups), - 5 - ) + groups["group 5"] = ["D", "E", "F"] + self.assertEqual(len(groups), 5) def test_len_subtract(self): groups = self.getGroups_generic() - groups.pop('group 4') - self.assertEqual( - len(groups), - 3 - ) - - + groups.pop("group 4") + self.assertEqual(len(groups), 3) # --- # Get @@ -122,10 +102,7 @@ def test_len_subtract(self): def test_get_fallback_default(self): groups = self.getGroups_generic() - self.assertEqual( - groups.get("test"), - None - ) + self.assertEqual(groups.get("test"), None) # ------- # Queries @@ -135,17 +112,11 @@ def test_find_found(self): groups = self.getGroups_generic() found = groups.findGlyph("A") found.sort() - self.assertEqual( - found, - [u"group 1", u"group 4"] - ) + self.assertEqual(found, ["group 1", "group 4"]) def test_find_not_found(self): groups = self.getGroups_generic() - self.assertEqual( - groups.findGlyph("five"), - [] - ) + self.assertEqual(groups.findGlyph("five"), []) def test_find_invalid_key(self): groups = self.getGroups_generic() @@ -162,10 +133,7 @@ def test_contains_not_found(self): def test_get_found(self): groups = self.getGroups_generic() - self.assertEqual( - groups["group 1"], - ("A", "B", "C") - ) + self.assertEqual(groups["group 1"], ("A", "B", "C")) def test_get_not_found(self): groups = self.getGroups_generic() @@ -182,43 +150,30 @@ def getGroups_kerning(self): "public.kern1.A": ["A", "Aacute"], "public.kern1.O": ["O", "D"], "public.kern2.A": ["A", "Aacute"], - "public.kern2.O": ["O", "C"] + "public.kern2.O": ["O", "C"], } groups.update(kerningGroups) return groups def test_side1KerningGroups(self): groups = self.getGroups_kerning() - expected = { - "public.kern1.A": ("A", "Aacute"), - "public.kern1.O": ("O", "D") - } + expected = {"public.kern1.A": ("A", "Aacute"), "public.kern1.O": ("O", "D")} self.assertEqual(groups.side1KerningGroups, expected) # self.assertEqual(super(groups, self)._get_side1KerningGroups(), expected) def test_get_side1KerningGroups(self): groups = self.getGroups_kerning() - expected = { - "public.kern1.A": ["A", "Aacute"], - "public.kern1.O": ["O", "D"] - } + expected = {"public.kern1.A": ["A", "Aacute"], "public.kern1.O": ["O", "D"]} self.assertEqual(groups._get_side1KerningGroups(), expected) - def test_side2KerningGroups(self): groups = self.getGroups_kerning() - expected = { - "public.kern2.A": ("A", "Aacute"), - "public.kern2.O": ("O", "C") - } + expected = {"public.kern2.A": ("A", "Aacute"), "public.kern2.O": ("O", "C")} self.assertEqual(groups.side2KerningGroups, expected) def test_get_side2KerningGroups(self): groups = self.getGroups_kerning() - expected = { - "public.kern1.A": ["A", "Aacute"], - "public.kern1.O": ["O", "D"] - } + expected = {"public.kern1.A": ["A", "Aacute"], "public.kern1.O": ["O", "D"]} self.assertEqual(groups._get_side1KerningGroups(), expected) # ---- @@ -227,10 +182,7 @@ def test_get_side2KerningGroups(self): def test_hash(self): groups = self.getGroups_generic() - self.assertEqual( - isinstance(groups, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(groups, collections.abc.Hashable), True) # -------- # Equality @@ -238,35 +190,23 @@ def test_hash(self): def test_object_equal_self(self): groups_one = self.getGroups_generic() - self.assertEqual( - groups_one, - groups_one - ) + self.assertEqual(groups_one, groups_one) def test_object_not_equal_other(self): groups_one = self.getGroups_generic() groups_two = self.getGroups_generic() - self.assertNotEqual( - groups_one, - groups_two - ) + self.assertNotEqual(groups_one, groups_two) def test_object_equal_self_variable_assignment(self): groups_one = self.getGroups_generic() a = groups_one - self.assertEqual( - groups_one, - a - ) + self.assertEqual(groups_one, a) def test_object_not_equal_other_variable_assignment(self): groups_one = self.getGroups_generic() groups_two = self.getGroups_generic() a = groups_one - self.assertNotEqual( - groups_two, - a - ) + self.assertNotEqual(groups_two, a) # --------------------- # RoboFab Compatibility @@ -275,11 +215,7 @@ def test_object_not_equal_other_variable_assignment(self): def test_remove(self): groups = self.getGroups_generic() groups.remove("group 2") - expected = { - "group 1": ("A", "B", "C"), - "group 3": (), - "group 4": ('A',) - } + expected = {"group 1": ("A", "B", "C"), "group 3": (), "group 4": ("A",)} self.assertEqual(groups.asDict(), expected) def test_remove_twice(self): @@ -299,7 +235,7 @@ def test_asDict(self): "group 1": ("A", "B", "C"), "group 2": ("x", "y", "z"), "group 3": (), - "group 4": ('A',) + "group 4": ("A",), } self.assertEqual(groups.asDict(), expected) @@ -309,7 +245,7 @@ def test_asDict(self): def test_iter(self): groups = self.getGroups_generic() - expected = ["group 1","group 2","group 3", "group 4"] + expected = ["group 1", "group 2", "group 3", "group 4"] listOfGroups = [] for groupName in groups: @@ -326,8 +262,7 @@ def test_iter_remove(self): self.assertEqual(groups.keys(), expected) - def test_values(self): groups = self.getGroups_generic() - expected = [("A", "B", "C"), ("x", "y", "z"),(),('A',)] + expected = [("A", "B", "C"), ("x", "y", "z"), (), ("A",)] self.assertEqual(groups.values().sort(), expected.sort()) diff --git a/Lib/fontParts/test/test_guideline.py b/Lib/fontParts/test/test_guideline.py index 24b4e221..721f61f4 100644 --- a/Lib/fontParts/test/test_guideline.py +++ b/Lib/fontParts/test/test_guideline.py @@ -4,7 +4,6 @@ class TestGuideline(unittest.TestCase): - def getGuideline_generic(self): guideline, _ = self.objectGenerator("guideline") guideline.x = 1 @@ -58,88 +57,55 @@ def test_reprContents_Layer(self): def test_x_get_generic(self): guideline = self.getGuideline_generic() - self.assertEqual( - guideline.x, - 1 - ) + self.assertEqual(guideline.x, 1) def test_x_get_fontGuideline(self): guideline = self.getGuideline_fontGuideline() - self.assertEqual( - guideline.x, - 1 - ) + self.assertEqual(guideline.x, 1) def test_x_get_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() - self.assertEqual( - guideline.x, - 1 - ) + self.assertEqual(guideline.x, 1) def test_x_set_valid_zero_generic(self): guideline = self.getGuideline_generic() guideline.x = 0 - self.assertEqual( - guideline.x, - 0 - ) + self.assertEqual(guideline.x, 0) def test_x_set_valid_zero_fontGuideline(self): guideline = self.getGuideline_fontGuideline() guideline.x = 0 - self.assertEqual( - guideline.x, - 0 - ) + self.assertEqual(guideline.x, 0) def test_x_set_valid_zero_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() guideline.x = 0 - self.assertEqual( - guideline.x, - 0 - ) + self.assertEqual(guideline.x, 0) def test_x_set_valid_positive(self): guideline = self.getGuideline_generic() guideline.x = 1 - self.assertEqual( - guideline.x, - 1 - ) + self.assertEqual(guideline.x, 1) def test_x_set_valid_negative(self): guideline = self.getGuideline_generic() guideline.x = -1 - self.assertEqual( - guideline.x, - -1 - ) + self.assertEqual(guideline.x, -1) def test_x_set_valid_positive_float(self): guideline = self.getGuideline_generic() guideline.x = 1.1 - self.assertEqual( - guideline.x, - 1.1 - ) + self.assertEqual(guideline.x, 1.1) def test_x_set_valid_negative_float(self): guideline = self.getGuideline_generic() guideline.x = -1.1 - self.assertEqual( - guideline.x, - -1.1 - ) + self.assertEqual(guideline.x, -1.1) def test_x_set_valid_None(self): guideline = self.getGuideline_generic() guideline.x = None - self.assertEqual( - guideline.x, - 0 - ) + self.assertEqual(guideline.x, 0) def test_x_set_invalid_string(self): guideline = self.getGuideline_generic() @@ -150,88 +116,55 @@ def test_x_set_invalid_string(self): def test_y_get_generic(self): guideline = self.getGuideline_generic() - self.assertEqual( - guideline.y, - 2 - ) + self.assertEqual(guideline.y, 2) def test_y_get_fontGuideline(self): guideline = self.getGuideline_fontGuideline() - self.assertEqual( - guideline.y, - 2 - ) + self.assertEqual(guideline.y, 2) def test_y_get_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() - self.assertEqual( - guideline.y, - 2 - ) + self.assertEqual(guideline.y, 2) def test_y_set_valid_zero_generic(self): guideline = self.getGuideline_generic() guideline.y = 0 - self.assertEqual( - guideline.y, - 0 - ) + self.assertEqual(guideline.y, 0) def test_y_set_valid_zero_fontGuideline(self): guideline = self.getGuideline_fontGuideline() guideline.y = 0 - self.assertEqual( - guideline.y, - 0 - ) + self.assertEqual(guideline.y, 0) def test_y_set_valid_zero_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() guideline.y = 0 - self.assertEqual( - guideline.y, - 0 - ) + self.assertEqual(guideline.y, 0) def test_y_set_valid_positive(self): guideline = self.getGuideline_generic() guideline.y = 1 - self.assertEqual( - guideline.y, - 1 - ) + self.assertEqual(guideline.y, 1) def test_y_set_valid_negative(self): guideline = self.getGuideline_generic() guideline.y = -1 - self.assertEqual( - guideline.y, - -1 - ) + self.assertEqual(guideline.y, -1) def test_y_set_valid_positive_float(self): guideline = self.getGuideline_generic() guideline.y = 1.1 - self.assertEqual( - guideline.y, - 1.1 - ) + self.assertEqual(guideline.y, 1.1) def test_y_set_valid_negative_float(self): guideline = self.getGuideline_generic() guideline.y = -1.1 - self.assertEqual( - guideline.y, - -1.1 - ) + self.assertEqual(guideline.y, -1.1) def test_y_set_valid_None(self): guideline = self.getGuideline_generic() guideline.y = None - self.assertEqual( - guideline.y, - 0 - ) + self.assertEqual(guideline.y, 0) def test_y_set_invalid_string(self): guideline = self.getGuideline_generic() @@ -242,104 +175,65 @@ def test_y_set_invalid_string(self): def test_angle_get_generic(self): guideline = self.getGuideline_generic() - self.assertEqual( - guideline.angle, - 90 - ) + self.assertEqual(guideline.angle, 90) def test_angle_get_fontGuideline(self): guideline = self.getGuideline_fontGuideline() - self.assertEqual( - guideline.angle, - 90 - ) + self.assertEqual(guideline.angle, 90) def test_angle_get_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() - self.assertEqual( - guideline.angle, - 90 - ) + self.assertEqual(guideline.angle, 90) def test_angle_set_valid_zero_generic(self): guideline = self.getGuideline_generic() guideline.angle = 0 - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_zero_fontGuideline(self): guideline = self.getGuideline_fontGuideline() guideline.angle = 0 - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_zero_glyphGuideline(self): guideline = self.getGuideline_glyphGuideline() guideline.angle = 0 - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_positive(self): guideline = self.getGuideline_generic() guideline.angle = 10 - self.assertEqual( - guideline.angle, - 10 - ) + self.assertEqual(guideline.angle, 10) def test_angle_set_valid_negative(self): guideline = self.getGuideline_generic() guideline.angle = -10 - self.assertEqual( - guideline.angle, - 350 - ) + self.assertEqual(guideline.angle, 350) def test_angle_set_valid_positive_float(self): guideline = self.getGuideline_generic() guideline.angle = 10.1 - self.assertEqual( - guideline.angle, - 10.1 - ) + self.assertEqual(guideline.angle, 10.1) def test_angle_set_valid_negative_float(self): guideline = self.getGuideline_generic() guideline.angle = -10.1 - self.assertEqual( - guideline.angle, - 349.9 - ) + self.assertEqual(guideline.angle, 349.9) def test_angle_set_valid_positive_edge(self): guideline = self.getGuideline_generic() guideline.angle = 360 - self.assertEqual( - guideline.angle, - 360 - ) + self.assertEqual(guideline.angle, 360) def test_angle_set_valid_negative_edge(self): guideline = self.getGuideline_generic() guideline.angle = -360 - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_None(self): guideline = self.getGuideline_generic() guideline.angle = None - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_invalid_positive_edge(self): guideline = self.getGuideline_generic() @@ -361,40 +255,28 @@ def test_angle_set_valid_none_x0_y0(self): guideline.x = 0 guideline.y = 0 guideline.angle = None - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_none_x1_y0(self): guideline = self.getGuideline_generic() guideline.x = 1 guideline.y = 0 guideline.angle = None - self.assertEqual( - guideline.angle, - 90 - ) + self.assertEqual(guideline.angle, 90) def test_angle_set_valid_none_x0_y1(self): guideline = self.getGuideline_generic() guideline.x = 0 guideline.y = 1 guideline.angle = None - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) def test_angle_set_valid_none_x1_y1(self): guideline = self.getGuideline_generic() guideline.x = 1 guideline.y = 1 guideline.angle = None - self.assertEqual( - guideline.angle, - 0 - ) + self.assertEqual(guideline.angle, 0) # index @@ -439,8 +321,8 @@ def test_name_get_none(self): def test_name_set_valid(self): guideline = self.getGuideline_generic() - guideline.name = u"foo" - self.assertEqual(guideline.name, u"foo") + guideline.name = "foo" + self.assertEqual(guideline.name, "foo") def test_name_set_none(self): guideline = self.getGuideline_generic() @@ -779,41 +661,27 @@ def test_round_angle(self): def test_hash_object_self(self): guideline_one = self.getGuideline_generic() - self.assertEqual( - hash(guideline_one), - hash(guideline_one) - ) + self.assertEqual(hash(guideline_one), hash(guideline_one)) def test_hash_object_other(self): guideline_one = self.getGuideline_generic() guideline_two = self.getGuideline_generic() - self.assertNotEqual( - hash(guideline_one), - hash(guideline_two) - ) + self.assertNotEqual(hash(guideline_one), hash(guideline_two)) def test_hash_object_self_variable_assignment(self): guideline_one = self.getGuideline_generic() a = guideline_one - self.assertEqual( - hash(guideline_one), - hash(a) - ) + self.assertEqual(hash(guideline_one), hash(a)) def test_hash_object_other_variable_assignment(self): guideline_one = self.getGuideline_generic() guideline_two = self.getGuideline_generic() a = guideline_one - self.assertNotEqual( - hash(guideline_two), - hash(a) - ) + self.assertNotEqual(hash(guideline_two), hash(a)) def test_is_hashable(self): guideline_one = self.getGuideline_generic() - self.assertTrue( - isinstance(guideline_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(guideline_one, collections.abc.Hashable)) # ------- # Parents @@ -825,10 +693,7 @@ def test_get_parent_font(self): glyph = layer.newGlyph("X") guideline = glyph.appendGuideline((0, 0), 90, "Test Guideline") self.assertIsNotNone(guideline.font) - self.assertEqual( - guideline.font, - font - ) + self.assertEqual(guideline.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -841,10 +706,7 @@ def test_get_parent_layer(self): glyph = layer.newGlyph("X") guideline = glyph.appendGuideline((0, 0), 90, "Test Guideline") self.assertIsNotNone(guideline.layer) - self.assertEqual( - guideline.layer, - layer - ) + self.assertEqual(guideline.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -856,10 +718,7 @@ def test_get_parent_glyph(self): glyph, _ = self.objectGenerator("glyph") guideline = glyph.appendGuideline((0, 0), 90, "Test Guideline") self.assertIsNotNone(guideline.glyph) - self.assertEqual( - guideline.glyph, - glyph - ) + self.assertEqual(guideline.glyph, glyph) def test_get_parent_noGlyph(self): guideline, _ = self.objectGenerator("guideline") @@ -872,10 +731,7 @@ def test_set_parent_glyph(self): guideline = self.getGuideline_generic() guideline.glyph = glyph self.assertIsNotNone(guideline.glyph) - self.assertEqual( - guideline.glyph, - glyph - ) + self.assertEqual(guideline.glyph, glyph) def test_set_parent_glyph_none(self): guideline, _ = self.objectGenerator("guideline") @@ -918,36 +774,24 @@ def test_set_parent_font_glyph_exists(self): def test_object_equal_self(self): guideline_one = self.getGuideline_generic() - self.assertEqual( - guideline_one, - guideline_one - ) + self.assertEqual(guideline_one, guideline_one) def test_object_not_equal_other(self): guideline_one = self.getGuideline_generic() guideline_two = self.getGuideline_generic() - self.assertNotEqual( - guideline_one, - guideline_two - ) + self.assertNotEqual(guideline_one, guideline_two) def test_object_equal_self_variable_assignment(self): guideline_one = self.getGuideline_generic() a = guideline_one a.x = 200 - self.assertEqual( - guideline_one, - a - ) + self.assertEqual(guideline_one, a) def test_object_not_equal_other_variable_assignment(self): guideline_one = self.getGuideline_generic() guideline_two = self.getGuideline_generic() a = guideline_one - self.assertNotEqual( - guideline_two, - a - ) + self.assertNotEqual(guideline_two, a) # --------- # Selection @@ -960,10 +804,7 @@ def test_selected_true(self): except NotImplementedError: return guideline.selected = True - self.assertEqual( - guideline.selected, - True - ) + self.assertEqual(guideline.selected, True) def test_not_selected_false(self): guideline = self.getGuideline_generic() @@ -971,7 +812,4 @@ def test_not_selected_false(self): guideline.selected = False except NotImplementedError: return - self.assertEqual( - guideline.selected, - False - ) + self.assertEqual(guideline.selected, False) diff --git a/Lib/fontParts/test/test_image.py b/Lib/fontParts/test/test_image.py index 323cb71e..1140010c 100644 --- a/Lib/fontParts/test/test_image.py +++ b/Lib/fontParts/test/test_image.py @@ -253,11 +253,10 @@ 73bdbc1371cd7100c18726fe1cc635e5ff7f6d102cb21055ee1c0000000049454e44ae 426082 """.strip().replace("\n", "") -testImageData = b"\x89PNG\r\n\x1a\n" + testPNGData.encode('utf-8') +testImageData = b"\x89PNG\r\n\x1a\n" + testPNGData.encode("utf-8") class TestImage(unittest.TestCase): - def getImage_generic(self): image, _ = self.objectGenerator("image") image.data = testImageData @@ -348,7 +347,7 @@ def test_bool_no_data(self): def test_bool_data_len_zero(self): image, _ = self.objectGenerator("image") try: - image.data = "".encode('utf-8') + image.data = "".encode("utf-8") except FontPartsError: raise unittest.SkipTest("Cannot set zero data") self.assertFalse(image) @@ -363,10 +362,7 @@ def test_get_parent_font(self): glyph = layer.newGlyph("X") image = glyph.image self.assertIsNotNone(image.font) - self.assertEqual( - image.font, - font - ) + self.assertEqual(image.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -379,10 +375,7 @@ def test_get_parent_layer(self): glyph = layer.newGlyph("X") image = glyph.image self.assertIsNotNone(image.layer) - self.assertEqual( - image.layer, - layer - ) + self.assertEqual(image.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -394,10 +387,7 @@ def test_get_parent_glyph(self): glyph, _ = self.objectGenerator("glyph") image = glyph.image self.assertIsNotNone(image.glyph) - self.assertEqual( - image.glyph, - glyph - ) + self.assertEqual(image.glyph, glyph) def test_get_parent_noGlyph(self): image, _ = self.objectGenerator("image") @@ -410,10 +400,7 @@ def test_set_parent_glyph(self): image = self.getImage_generic() image.glyph = glyph self.assertIsNotNone(image.glyph) - self.assertEqual( - image.glyph, - glyph - ) + self.assertEqual(image.glyph, glyph) def test_set_parent_glyph_none(self): image, _ = self.objectGenerator("image") @@ -434,34 +421,22 @@ def test_set_parent_glyph_exists(self): def test_data_get(self): image = self.getImage_generic() # get - self.assertEqual( - image.data, - testImageData - ) + self.assertEqual(image.data, testImageData) def test_data_set_valid(self): image = self.getImage_generic() image.data = testImageData - self.assertEqual( - image.data, - testImageData - ) + self.assertEqual(image.data, testImageData) def test_data_get_direct(self): image = self.getImage_generic() # get - self.assertEqual( - image._get_base_data(), - testImageData - ) + self.assertEqual(image._get_base_data(), testImageData) def test_data_set_valid_direct(self): image = self.getImage_generic() image._set_base_data(testImageData) - self.assertEqual( - image.data, - testImageData - ) + self.assertEqual(image.data, testImageData) def test_data_set_invalid(self): image = self.getImage_generic() @@ -471,7 +446,7 @@ def test_data_set_invalid(self): def test_data_set_invalid_png(self): image, _ = self.objectGenerator("image") with self.assertRaises(FontPartsError): - image.data = testPNGData.encode('utf-8') + image.data = testPNGData.encode("utf-8") # ----- # Color @@ -479,10 +454,7 @@ def test_data_set_invalid_png(self): def test_get_color_no_parent(self): image = self.getImage_generic() - self.assertEqual( - image.color, - (1, 0, 1, 1) - ) + self.assertEqual(image.color, (1, 0, 1, 1)) def test_get_color_parent(self): font, _ = self.objectGenerator("font") @@ -492,18 +464,12 @@ def test_get_color_parent(self): image.data = testImageData image.transformation = (1, 0, 0, 1, 0, 0) image.color = (1, 0, 1, 1) - self.assertEqual( - image.color, - (1, 0, 1, 1) - ) + self.assertEqual(image.color, (1, 0, 1, 1)) def test_get_color_no_parent_none(self): image = self.getImage_generic() image.color = None - self.assertEqual( - image.color, - None - ) + self.assertEqual(image.color, None) def test_get_color_parent_none(self): font, _ = self.objectGenerator("font") @@ -512,23 +478,14 @@ def test_get_color_parent_none(self): image = glyph.image image.data = testImageData image.transformation = (1, 0, 0, 1, 0, 0) - self.assertEqual( - image.color, - None - ) + self.assertEqual(image.color, None) def test_set_color(self): image = self.getImage_generic() image.color = (0, 1, 0, 0) - self.assertEqual( - image.color, - (0, 1, 0, 0) - ) + self.assertEqual(image.color, (0, 1, 0, 0)) image.color = (0.5, 0.5, 0.5, 0.5) - self.assertEqual( - image.color, - (0.5, 0.5, 0.5, 0.5) - ) + self.assertEqual(image.color, (0.5, 0.5, 0.5, 0.5)) def test_set_color_invalid(self): image = self.getImage_generic() @@ -541,23 +498,14 @@ def test_set_color_invalid(self): def test_get_transformation(self): image = self.getImage_generic() - self.assertEqual( - image.transformation, - (1, 0, 0, 1, 0, 0) - ) + self.assertEqual(image.transformation, (1, 0, 0, 1, 0, 0)) def test_set_tranformation(self): image = self.getImage_generic() image.transformation = (0, 1, 1, 0, 1, 1) - self.assertEqual( - image.transformation, - (0, 1, 1, 0, 1, 1) - ) + self.assertEqual(image.transformation, (0, 1, 1, 0, 1, 1)) image.transformation = (0.5, 0.5, 0.5, 0.5, 0.5, 0.5) - self.assertEqual( - image.transformation, - (0.5, 0.5, 0.5, 0.5, 0.5, 0.5) - ) + self.assertEqual(image.transformation, (0.5, 0.5, 0.5, 0.5, 0.5, 0.5)) def test_set_tranformation_invalid(self): image = self.getImage_generic() @@ -567,18 +515,12 @@ def test_set_tranformation_invalid(self): def test_transformBy_valid_no_origin(self): image = self.getImage_generic() image.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - image.transformation, - (2, 0, 0, 3, -3, 2) - ) + self.assertEqual(image.transformation, (2, 0, 0, 3, -3, 2)) def test_transformBy_valid_origin(self): image = self.getImage_generic() image.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - image.transformation, - (2, 0, 0, 2, -1, -2) - ) + self.assertEqual(image.transformation, (2, 0, 0, 2, -1, -2)) # ------ # Offset @@ -586,26 +528,17 @@ def test_transformBy_valid_origin(self): def test_get_offset(self): image = self.getImage_generic() - self.assertEqual( - image.offset, - (0, 0) - ) + self.assertEqual(image.offset, (0, 0)) def test_get_offset_set(self): image = self.getImage_generic() image.offset = (1, 4.5) - self.assertEqual( - image.offset, - (1, 4.5) - ) + self.assertEqual(image.offset, (1, 4.5)) def test_set_offset(self): image = self.getImage_generic() image.offset = (2.3, 5) - self.assertEqual( - image.offset, - (2.3, 5) - ) + self.assertEqual(image.offset, (2.3, 5)) def test_set_offset_invalid_none(self): image = self.getImage_generic() @@ -623,26 +556,17 @@ def test_set_offset_invalid_string(self): def test_get_scale(self): image = self.getImage_generic() - self.assertEqual( - image.scale, - (1, 1) - ) + self.assertEqual(image.scale, (1, 1)) def test_get_scale_set(self): image = self.getImage_generic() image.scale = (2, 2.5) - self.assertEqual( - image.scale, - (2, 2.5) - ) + self.assertEqual(image.scale, (2, 2.5)) def test_set_scale(self): image = self.getImage_generic() image.scale = (2.3, 5) - self.assertEqual( - image.scale, - (2.3, 5) - ) + self.assertEqual(image.scale, (2.3, 5)) def test_set_scale_invalid_none(self): image = self.getImage_generic() @@ -662,19 +586,13 @@ def test_round(self): image = self.getImage_generic() image.offset = (1.1, 1.1) image.round() - self.assertEqual( - image.offset, - (1, 1) - ) + self.assertEqual(image.offset, (1, 1)) def test_round_half(self): image = self.getImage_generic() image.offset = (1.5, 1.5) image.round() - self.assertEqual( - image.offset, - (2, 2) - ) + self.assertEqual(image.offset, (2, 2)) # ---- # Hash @@ -682,41 +600,27 @@ def test_round_half(self): def test_hash_object_self(self): image_one = self.getImage_generic() - self.assertEqual( - hash(image_one), - hash(image_one) - ) + self.assertEqual(hash(image_one), hash(image_one)) def test_hash_object_other(self): image_one = self.getImage_generic() image_two = self.getImage_generic() - self.assertNotEqual( - hash(image_one), - hash(image_two) - ) + self.assertNotEqual(hash(image_one), hash(image_two)) def test_hash_object_self_variable_assignment(self): image_one = self.getImage_generic() a = image_one - self.assertEqual( - hash(image_one), - hash(a) - ) + self.assertEqual(hash(image_one), hash(a)) def test_hash_object_other_variable_assignment(self): image_one = self.getImage_generic() image_two = self.getImage_generic() a = image_one - self.assertNotEqual( - hash(image_two), - hash(a) - ) + self.assertNotEqual(hash(image_two), hash(a)) def test_is_hashable(self): image_one = self.getImage_generic() - self.assertTrue( - isinstance(image_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(image_one, collections.abc.Hashable)) # -------- # Equality @@ -724,35 +628,23 @@ def test_is_hashable(self): def test_object_equal_self(self): image_one = self.getImage_generic() - self.assertEqual( - image_one, - image_one - ) + self.assertEqual(image_one, image_one) def test_object_not_equal_other(self): image_one = self.getImage_generic() image_two = self.getImage_generic() - self.assertNotEqual( - image_one, - image_two - ) + self.assertNotEqual(image_one, image_two) def test_object_equal_self_variable_assignment(self): image_one = self.getImage_generic() a = image_one - self.assertEqual( - image_one, - a - ) + self.assertEqual(image_one, a) def test_object_not_equal_other_variable_assignment(self): image_one = self.getImage_generic() image_two = self.getImage_generic() a = image_one - self.assertNotEqual( - image_two, - a - ) + self.assertNotEqual(image_two, a) # --------- # Selection @@ -765,10 +657,7 @@ def test_selected_true(self): except NotImplementedError: return image.selected = True - self.assertEqual( - image.selected, - True - ) + self.assertEqual(image.selected, True) def test_selected_false(self): image = self.getImage_generic() @@ -776,7 +665,4 @@ def test_selected_false(self): image.selected = False except NotImplementedError: return - self.assertEqual( - image.selected, - False - ) + self.assertEqual(image.selected, False) diff --git a/Lib/fontParts/test/test_info.py b/Lib/fontParts/test/test_info.py index b5aa63d7..3e10eca7 100644 --- a/Lib/fontParts/test/test_info.py +++ b/Lib/fontParts/test/test_info.py @@ -3,7 +3,6 @@ class TestInfo(unittest.TestCase): - def getInfo_generic(self): info, _ = self.objectGenerator("info") info.unitsPerEm = 1000 @@ -15,26 +14,17 @@ def getInfo_generic(self): def test_get_unitsPerEm(self): info = self.getInfo_generic() - self.assertEqual( - info.unitsPerEm, - 1000 - ) + self.assertEqual(info.unitsPerEm, 1000) def test_set_valid_unitsPerEm_int(self): info = self.getInfo_generic() info.unitsPerEm = 2000 - self.assertEqual( - info.unitsPerEm, - 2000 - ) + self.assertEqual(info.unitsPerEm, 2000) def test_set_valid_unitsPerEm_float(self): info = self.getInfo_generic() info.unitsPerEm = 2000.1 - self.assertEqual( - info.unitsPerEm, - 2000.1 - ) + self.assertEqual(info.unitsPerEm, 2000.1) def test_set_invalid_unitsPerEm_negative(self): info = self.getInfo_generic() @@ -52,10 +42,7 @@ def test_set_invalid_unitsPerEm_string(self): def test_hash(self): info = self.getInfo_generic() - self.assertEqual( - isinstance(info, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(info, collections.abc.Hashable), True) # -------- # Equality @@ -63,35 +50,23 @@ def test_hash(self): def test_object_equal_self(self): info_one = self.getInfo_generic() - self.assertEqual( - info_one, - info_one - ) + self.assertEqual(info_one, info_one) def test_object_not_equal_other(self): info_one = self.getInfo_generic() info_two = self.getInfo_generic() - self.assertNotEqual( - info_one, - info_two - ) + self.assertNotEqual(info_one, info_two) def test_object_equal_self_variable_assignment(self): info_one = self.getInfo_generic() a = info_one - self.assertEqual( - info_one, - a - ) + self.assertEqual(info_one, a) def test_object_not_equal_other_variable_assignment(self): info_one = self.getInfo_generic() info_two = self.getInfo_generic() a = info_one - self.assertNotEqual( - info_two, - a - ) + self.assertNotEqual(info_two, a) # ----- # Round @@ -101,10 +76,7 @@ def test_round_unitsPerEm(self): info = self.getInfo_generic() info.unitsPerEm = 2000.125 info.round() - self.assertEqual( - info.unitsPerEm, - 2000 - ) + self.assertEqual(info.unitsPerEm, 2000) # ------ # Update @@ -112,6 +84,7 @@ def test_round_unitsPerEm(self): def test_update(self): from fontTools.ufoLib import fontInfoAttributesVersion3ValueData + info1 = self.getInfo_generic() info1.familyName = "test1" info1.unitsPerEm = 1000 @@ -132,11 +105,10 @@ def test_interpolate_unitsPerEm_without_rounding(self): font_max, _ = self.objectGenerator("font") font_min.info.unitsPerEm = 1000 font_max.info.unitsPerEm = 2000 - interpolated_font.info.interpolate(0.5154, font_min.info, font_max.info, round=False) - self.assertEqual( - interpolated_font.info.unitsPerEm, - 1515.4 + interpolated_font.info.interpolate( + 0.5154, font_min.info, font_max.info, round=False ) + self.assertEqual(interpolated_font.info.unitsPerEm, 1515.4) def test_interpolate_unitsPerEm_with_rounding(self): interpolated_font, _ = self.objectGenerator("font") @@ -144,8 +116,7 @@ def test_interpolate_unitsPerEm_with_rounding(self): font_max, _ = self.objectGenerator("font") font_min.info.unitsPerEm = 1000 font_max.info.unitsPerEm = 2000 - interpolated_font.info.interpolate(0.5154, font_min.info, font_max.info, round=True) - self.assertEqual( - interpolated_font.info.unitsPerEm, - 1515 + interpolated_font.info.interpolate( + 0.5154, font_min.info, font_max.info, round=True ) + self.assertEqual(interpolated_font.info.unitsPerEm, 1515) diff --git a/Lib/fontParts/test/test_kerning.py b/Lib/fontParts/test/test_kerning.py index 45322803..b4752ada 100644 --- a/Lib/fontParts/test/test_kerning.py +++ b/Lib/fontParts/test/test_kerning.py @@ -3,19 +3,20 @@ class TestKerning(unittest.TestCase): - def getKerning_generic(self): font, _ = self.objectGenerator("font") groups = font.groups groups["public.kern1.X"] = ["A", "B", "C"] groups["public.kern2.X"] = ["A", "B", "C"] kerning = font.kerning - kerning.update({ - ("public.kern1.X", "public.kern2.X"): 100, - ("B", "public.kern2.X"): 101, - ("public.kern1.X", "B"): 102, - ("A", "A"): 103, - }) + kerning.update( + { + ("public.kern1.X", "public.kern2.X"): 100, + ("B", "public.kern2.X"): 101, + ("public.kern1.X", "B"): 102, + ("A", "A"): 103, + } + ) return kerning def getKerning_font2(self): @@ -24,12 +25,14 @@ def getKerning_font2(self): groups["public.kern1.X"] = ["A", "B", "C"] groups["public.kern2.X"] = ["A", "B", "C"] kerning = font.kerning - kerning.update({ - ("public.kern1.X", "public.kern2.X"): 200, - ("B", "public.kern2.X"): 201, - ("public.kern1.X", "B"): 202, - ("A", "A"): 203, - }) + kerning.update( + { + ("public.kern1.X", "public.kern2.X"): 200, + ("B", "public.kern2.X"): 201, + ("public.kern1.X", "B"): 202, + ("A", "A"): 203, + } + ) return kerning # --- @@ -38,18 +41,12 @@ def getKerning_font2(self): def test_len_initial(self): kerning = self.getKerning_generic() - self.assertEqual( - len(kerning), - 4 - ) + self.assertEqual(len(kerning), 4) def test_len_clear(self): kerning = self.getKerning_generic() kerning.clear() - self.assertEqual( - len(kerning), - 0 - ) + self.assertEqual(len(kerning), 0) # -------- # contains @@ -57,31 +54,19 @@ def test_len_clear(self): def test_contains_glyph_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - ('A', 'A') in kerning, - True - ) + self.assertEqual(("A", "A") in kerning, True) def test_contains_group_group(self): kerning = self.getKerning_generic() - self.assertEqual( - ("public.kern1.X", "public.kern2.X") in kerning, - True - ) + self.assertEqual(("public.kern1.X", "public.kern2.X") in kerning, True) def test_contains_glyph_group(self): kerning = self.getKerning_generic() - self.assertEqual( - ("B", "public.kern2.X") in kerning, - True - ) + self.assertEqual(("B", "public.kern2.X") in kerning, True) def test_contains_missing_glyph_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - ("H", "H") in kerning, - False - ) + self.assertEqual(("H", "H") in kerning, False) # --- # del @@ -90,17 +75,11 @@ def test_contains_missing_glyph_glyph(self): def test_del(self): kerning = self.getKerning_generic() # Be sure it is here before deleting - self.assertEqual( - ('A', 'A') in kerning, - True - ) + self.assertEqual(("A", "A") in kerning, True) # Delete - del kerning[('A', 'A')] + del kerning[("A", "A")] # Test - self.assertEqual( - ('A', 'A') in kerning, - False - ) + self.assertEqual(("A", "A") in kerning, False) # --- # get @@ -108,49 +87,28 @@ def test_del(self): def test_get_glyph_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning[('A', 'A')], - 103 - ) + self.assertEqual(kerning[("A", "A")], 103) def test_get_group_group(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning[("public.kern1.X", "public.kern2.X")], - 100 - ) + self.assertEqual(kerning[("public.kern1.X", "public.kern2.X")], 100) def test_get_glyph_group(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning[("B", "public.kern2.X")], - 101 - ) + self.assertEqual(kerning[("B", "public.kern2.X")], 101) def test_get_group_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning[("public.kern1.X", "B")], - 102 - ) + self.assertEqual(kerning[("public.kern1.X", "B")], 102) def test_get_fallback_default(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.get(("F", "F")), - None - ) + self.assertEqual(kerning.get(("F", "F")), None) def test_get_fallback_default_user(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.get(("F", "F"), None), - None - ) - self.assertEqual( - kerning.get(("F", "F"), 0), - 0 - ) + self.assertEqual(kerning.get(("F", "F"), None), None) + self.assertEqual(kerning.get(("F", "F"), 0), 0) # --- # set @@ -158,35 +116,23 @@ def test_get_fallback_default_user(self): def test_set_glyph_glyph(self): kerning = self.getKerning_generic() - kerning[('A', 'A')] = 1 - self.assertEqual( - kerning[('A', 'A')], - 1 - ) + kerning[("A", "A")] = 1 + self.assertEqual(kerning[("A", "A")], 1) def test_set_group_group(self): kerning = self.getKerning_generic() kerning[("public.kern1.X", "public.kern2.X")] = 2 - self.assertEqual( - kerning[("public.kern1.X", "public.kern2.X")], - 2 - ) + self.assertEqual(kerning[("public.kern1.X", "public.kern2.X")], 2) def test_set_glyph_group(self): kerning = self.getKerning_generic() kerning[("B", "public.kern2.X")] = 3 - self.assertEqual( - kerning[("B", "public.kern2.X")], - 3 - ) + self.assertEqual(kerning[("B", "public.kern2.X")], 3) def test_set_group_glyph(self): kerning = self.getKerning_generic() kerning[("public.kern1.X", "B")] = 4 - self.assertEqual( - kerning[("public.kern1.X", "B")], - 4 - ) + self.assertEqual(kerning[("public.kern1.X", "B")], 4) # ---- # Find @@ -194,38 +140,23 @@ def test_set_group_glyph(self): def test_find_glyph_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.find(('A', 'A')), - 103 - ) + self.assertEqual(kerning.find(("A", "A")), 103) def test_find_glyph_glyph_none(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.find(('D', 'D')), - None - ) + self.assertEqual(kerning.find(("D", "D")), None) def test_find_group_glyph(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.find(('A', 'B')), - 102 - ) + self.assertEqual(kerning.find(("A", "B")), 102) def test_find_glyph_group(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.find(('B', 'B')), - 101 - ) + self.assertEqual(kerning.find(("B", "B")), 101) def test_find_group_group(self): kerning = self.getKerning_generic() - self.assertEqual( - kerning.find(('C', 'C')), - 100 - ) + self.assertEqual(kerning.find(("C", "C")), 100) # ---- # Hash @@ -233,10 +164,7 @@ def test_find_group_group(self): def test_hash(self): kerning = self.getKerning_generic() - self.assertEqual( - isinstance(kerning, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(kerning, collections.abc.Hashable), True) # -------- # Equality @@ -244,35 +172,23 @@ def test_hash(self): def test_object_equal_self(self): kerning_one = self.getKerning_generic() - self.assertEqual( - kerning_one, - kerning_one - ) + self.assertEqual(kerning_one, kerning_one) def test_object_not_equal_other(self): kerning_one = self.getKerning_generic() kerning_two = self.getKerning_generic() - self.assertNotEqual( - kerning_one, - kerning_two - ) + self.assertNotEqual(kerning_one, kerning_two) def test_object_equal_self_variable_assignment(self): kerning_one = self.getKerning_generic() a = kerning_one - self.assertEqual( - kerning_one, - a - ) + self.assertEqual(kerning_one, a) def test_object_not_equal_other_variable_assignment(self): kerning_one = self.getKerning_generic() kerning_two = self.getKerning_generic() a = kerning_one - self.assertNotEqual( - kerning_two, - a - ) + self.assertNotEqual(kerning_two, a) # ------------- # Interpolation @@ -284,10 +200,7 @@ def test_interpolation_without_rounding(self): kerning_max = self.getKerning_font2() interpolated.interpolate(0.515, kerning_min, kerning_max, round=False) - self.assertEqual( - interpolated[("public.kern1.X", "public.kern2.X")], - 151.5 - ) + self.assertEqual(interpolated[("public.kern1.X", "public.kern2.X")], 151.5) def test_interpolation_with_rounding(self): interpolated = self.getKerning_generic() @@ -295,7 +208,4 @@ def test_interpolation_with_rounding(self): kerning_max = self.getKerning_font2() interpolated.interpolate(0.515, kerning_min, kerning_max, round=True) - self.assertEqual( - interpolated[("public.kern1.X", "public.kern2.X")], - 152 - ) + self.assertEqual(interpolated[("public.kern1.X", "public.kern2.X")], 152) diff --git a/Lib/fontParts/test/test_layer.py b/Lib/fontParts/test/test_layer.py index 5f11499b..538ffde4 100644 --- a/Lib/fontParts/test/test_layer.py +++ b/Lib/fontParts/test/test_layer.py @@ -3,7 +3,6 @@ class TestLayer(unittest.TestCase): - # ------ # Glyphs # ------ @@ -16,10 +15,7 @@ def getLayer_glyphs(self): def test_len(self): layer = self.getLayer_glyphs() - self.assertEqual( - len(layer), - 4 - ) + self.assertEqual(len(layer), 4) def _testInsertGlyph(self, setGlyphName=True): layer, _ = self.objectGenerator("layer") @@ -34,10 +30,7 @@ def _testInsertGlyph(self, setGlyphName=True): glyph.name = "test" layer["test"] = glyph self.assertTrue("test" in layer) - self.assertEqual( - layer["test"].bounds, - glyph.bounds - ) + self.assertEqual(layer["test"].bounds, glyph.bounds) def test_set_glyph(self): self._testInsertGlyph(setGlyphName=True) @@ -47,10 +40,7 @@ def test_set_glyph_with_name_None(self): def test_get_glyph_in_font(self): layer = self.getLayer_glyphs() - self.assertEqual( - layer["A"].name, - "A" - ) + self.assertEqual(layer["A"].name, "A") def test_get_glyph_not_in_font(self): layer = self.getLayer_glyphs() @@ -63,41 +53,27 @@ def test_get_glyph_not_in_font(self): def test_hash_object_self(self): layer_one = self.getLayer_glyphs() - self.assertEqual( - hash(layer_one), - hash(layer_one) - ) + self.assertEqual(hash(layer_one), hash(layer_one)) def test_hash_object_other(self): layer_one = self.getLayer_glyphs() layer_two = self.getLayer_glyphs() - self.assertNotEqual( - hash(layer_one), - hash(layer_two) - ) + self.assertNotEqual(hash(layer_one), hash(layer_two)) def test_hash_object_self_variable_assignment(self): layer_one = self.getLayer_glyphs() a = layer_one - self.assertEqual( - hash(layer_one), - hash(a) - ) + self.assertEqual(hash(layer_one), hash(a)) def test_hash_object_other_variable_assignment(self): layer_one = self.getLayer_glyphs() layer_two = self.getLayer_glyphs() a = layer_one - self.assertNotEqual( - hash(layer_two), - hash(a) - ) + self.assertNotEqual(hash(layer_two), hash(a)) def test_is_hashable(self): layer_one = self.getLayer_glyphs() - self.assertTrue( - isinstance(layer_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(layer_one, collections.abc.Hashable)) # -------- # Equality @@ -105,35 +81,23 @@ def test_is_hashable(self): def test_object_equal_self(self): layer_one = self.getLayer_glyphs() - self.assertEqual( - layer_one, - layer_one - ) + self.assertEqual(layer_one, layer_one) def test_object_not_equal_other(self): layer_one = self.getLayer_glyphs() layer_two = self.getLayer_glyphs() - self.assertNotEqual( - layer_one, - layer_two - ) + self.assertNotEqual(layer_one, layer_two) def test_object_equal_self_variable_assignment(self): layer_one = self.getLayer_glyphs() a = layer_one - self.assertEqual( - layer_one, - a - ) + self.assertEqual(layer_one, a) def test_object_not_equal_self_variable_assignment(self): layer_one = self.getLayer_glyphs() layer_two = self.getLayer_glyphs() a = layer_one - self.assertNotEqual( - layer_two, - a - ) + self.assertNotEqual(layer_two, a) # --------- # Selection @@ -146,10 +110,7 @@ def test_selected_true(self): except NotImplementedError: return layer.selected = True - self.assertEqual( - layer.selected, - True - ) + self.assertEqual(layer.selected, True) def test_selected_false(self): layer = self.getLayer_glyphs() @@ -157,10 +118,7 @@ def test_selected_false(self): layer.selected = False except NotImplementedError: return - self.assertEqual( - layer.selected, - False - ) + self.assertEqual(layer.selected, False) # Glyphs @@ -170,10 +128,7 @@ def test_selectedGlyphs_default(self): layer.selected = False except NotImplementedError: return - self.assertEqual( - layer.selectedGlyphs, - () - ) + self.assertEqual(layer.selectedGlyphs, ()) def test_selectedGlyphs_setSubObject(self): layer = self.getLayer_glyphs() @@ -187,7 +142,7 @@ def test_selectedGlyphs_setSubObject(self): glyph2.selected = True self.assertEqual( tuple(sorted(layer.selectedGlyphs, key=lambda glyph: glyph.name)), - (glyph1, glyph2) + (glyph1, glyph2), ) def test_selectedGlyphs_setFilledList(self): @@ -201,7 +156,7 @@ def test_selectedGlyphs_setFilledList(self): layer.selectedGlyphs = [glyph3, glyph4] self.assertEqual( tuple(sorted(layer.selectedGlyphs, key=lambda glyph: glyph.name)), - (glyph3, glyph4) + (glyph3, glyph4), ) def test_selectedGlyphs_setEmptyList(self): @@ -213,10 +168,7 @@ def test_selectedGlyphs_setEmptyList(self): glyph1 = layer["A"] glyph1.selected = True layer.selectedGlyphs = [] - self.assertEqual( - layer.selectedGlyphs, - () - ) + self.assertEqual(layer.selectedGlyphs, ()) # Glyph Names @@ -226,10 +178,7 @@ def test_selectedGlyphNames_default(self): layer.selected = False except NotImplementedError: return - self.assertEqual( - layer.selectedGlyphs, - () - ) + self.assertEqual(layer.selectedGlyphs, ()) def test_selectedGlyphNames_setSubObject(self): layer = self.getLayer_glyphs() @@ -241,10 +190,7 @@ def test_selectedGlyphNames_setSubObject(self): glyph2 = layer["B"] glyph1.selected = True glyph2.selected = True - self.assertEqual( - tuple(sorted(layer.selectedGlyphNames)), - ("A", "B") - ) + self.assertEqual(tuple(sorted(layer.selectedGlyphNames)), ("A", "B")) def test_selectedGlyphNames_setFilledList(self): layer = self.getLayer_glyphs() @@ -253,10 +199,7 @@ def test_selectedGlyphNames_setFilledList(self): except NotImplementedError: return layer.selectedGlyphNames = ["C", "D"] - self.assertEqual( - tuple(sorted(layer.selectedGlyphNames)), - ("C", "D") - ) + self.assertEqual(tuple(sorted(layer.selectedGlyphNames)), ("C", "D")) def test_selectedGlyphNames_setEmptyList(self): layer = self.getLayer_glyphs() @@ -267,7 +210,4 @@ def test_selectedGlyphNames_setEmptyList(self): glyph1 = layer["A"] glyph1.selected = True layer.selectedGlyphNames = [] - self.assertEqual( - layer.selectedGlyphNames, - () - ) + self.assertEqual(layer.selectedGlyphNames, ()) diff --git a/Lib/fontParts/test/test_lib.py b/Lib/fontParts/test/test_lib.py index 88159d66..085bb50b 100644 --- a/Lib/fontParts/test/test_lib.py +++ b/Lib/fontParts/test/test_lib.py @@ -3,15 +3,9 @@ class TestLib(unittest.TestCase): - def getLib_generic(self): lib, _ = self.objectGenerator("lib") - lib.update({ - "key 1": ["A", "B", "C"], - "key 2": "x", - "key 3": [], - "key 4": 20 - }) + lib.update({"key 1": ["A", "B", "C"], "key 2": "x", "key 3": [], "key 4": 20}) return lib # ---- @@ -31,18 +25,12 @@ def test_reprContents(self): def test_len_initial(self): lib = self.getLib_generic() - self.assertEqual( - len(lib), - 4 - ) + self.assertEqual(len(lib), 4) def test_len_clear(self): lib = self.getLib_generic() lib.clear() - self.assertEqual( - len(lib), - 0 - ) + self.assertEqual(len(lib), 0) # ------- # Parents @@ -55,10 +43,7 @@ def test_get_parent_glyph(self): lib, _ = self.objectGenerator("lib") lib.glyph = glyph self.assertIsNotNone(lib.glyph) - self.assertEqual( - lib.glyph, - glyph - ) + self.assertEqual(lib.glyph, glyph) def test_get_parent_noGlyph(self): lib, _ = self.objectGenerator("lib") @@ -71,10 +56,7 @@ def test_set_parent_glyph(self): lib, _ = self.objectGenerator("lib") lib.glyph = glyph self.assertIsNotNone(lib.glyph) - self.assertEqual( - lib.glyph, - glyph - ) + self.assertEqual(lib.glyph, glyph) # Font @@ -85,10 +67,7 @@ def test_get_parent_font(self): lib, _ = self.objectGenerator("lib") lib.glyph = glyph self.assertIsNotNone(lib.font) - self.assertEqual( - lib.font, - font - ) + self.assertEqual(lib.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -103,10 +82,7 @@ def test_get_parent_noFont(self): def test_keys(self): lib = self.getLib_generic() - self.assertEqual( - sorted(lib.keys()), - ["key 1", "key 2", "key 3", "key 4"] - ) + self.assertEqual(sorted(lib.keys()), ["key 1", "key 2", "key 3", "key 4"]) def test_contains_found(self): lib = self.getLib_generic() @@ -118,10 +94,7 @@ def test_contains_not_found(self): def test_get_found(self): lib = self.getLib_generic() - self.assertEqual( - lib["key 1"], - ["A", "B", "C"] - ) + self.assertEqual(lib["key 1"], ["A", "B", "C"]) # ---- # Hash @@ -129,10 +102,7 @@ def test_get_found(self): def test_hash(self): lib = self.getLib_generic() - self.assertEqual( - isinstance(lib, collections.abc.Hashable), - True - ) + self.assertEqual(isinstance(lib, collections.abc.Hashable), True) # -------- # Equality @@ -140,32 +110,20 @@ def test_hash(self): def test_object_equal_self(self): lib_one = self.getLib_generic() - self.assertEqual( - lib_one, - lib_one - ) + self.assertEqual(lib_one, lib_one) def test_object_not_equal_other(self): lib_one = self.getLib_generic() lib_two = self.getLib_generic() - self.assertNotEqual( - lib_one, - lib_two - ) + self.assertNotEqual(lib_one, lib_two) def test_object_equal_self_variable_assignment(self): lib_one = self.getLib_generic() a = lib_one - self.assertEqual( - lib_one, - a - ) + self.assertEqual(lib_one, a) def test_object_not_equal_other_variable_assignment(self): lib_one = self.getLib_generic() lib_two = self.getLib_generic() a = lib_one - self.assertNotEqual( - lib_two, - a - ) + self.assertNotEqual(lib_two, a) diff --git a/Lib/fontParts/test/test_normalizers.py b/Lib/fontParts/test/test_normalizers.py index 19756f88..009c2a29 100644 --- a/Lib/fontParts/test/test_normalizers.py +++ b/Lib/fontParts/test/test_normalizers.py @@ -3,7 +3,6 @@ class TestNormalizers(unittest.TestCase): - # ---- # Font # ---- @@ -37,12 +36,12 @@ def test_normalizeLayerOrder_valid(self): self.assertIsInstance(result, tuple) for i in result: self.assertIsInstance(i, str) - self.assertEqual(result, (u"A", u"B", u"C", u"D", u"E")) + self.assertEqual(result, ("A", "B", "C", "D", "E")) def test_normalizeLayerOrder_validTuple(self): font = self.getFont_layers() result = normalizers.normalizeLayerOrder(tuple(["A", "B", "C", "D", "E"]), font) - self.assertEqual(result, (u"A", u"B", u"C", u"D", u"E")) + self.assertEqual(result, ("A", "B", "C", "D", "E")) def test_normalizeLayerOrder_notList(self): font = self.getFont_layers() @@ -69,7 +68,7 @@ def test_normalizeDefaultLayerName_valid(self): font = self.getFont_layers() result = normalizers.normalizeDefaultLayerName("B", font) self.assertIsInstance(result, str) - self.assertEqual(result, u"B") + self.assertEqual(result, "B") def test_normalizeDefaultLayerName_notValidLayerName(self): font = self.getFont_layers() @@ -88,11 +87,11 @@ def test_normalizeGlyphOrder_valid(self): self.assertIsInstance(result, tuple) for i in result: self.assertIsInstance(i, str) - self.assertEqual(result, (u"A", u"B", u"C", u"D", u"E")) + self.assertEqual(result, ("A", "B", "C", "D", "E")) def test_normalizeGlyphOrder_validTuple(self): result = normalizers.normalizeGlyphOrder(tuple(["A", "B", "C", "D", "E"])) - self.assertEqual(result, (u"A", u"B", u"C", u"D", u"E")) + self.assertEqual(result, ("A", "B", "C", "D", "E")) def test_normalizeGlyphOrder_notList(self): with self.assertRaises(TypeError): @@ -115,16 +114,16 @@ def test_normalizeGlyphOrder_duplicate(self): def test_normalizeKerningKey_validGlyphs(self): result = normalizers.normalizeKerningKey(("A", "B")) self.assertIsInstance(result, tuple) - self.assertEqual(result, (u"A", u"B")) + self.assertEqual(result, ("A", "B")) def test_normalizeKerningKey_validGroups(self): result = normalizers.normalizeKerningKey(("public.kern1.A", "public.kern2.B")) self.assertIsInstance(result, tuple) - self.assertEqual(result, (u"public.kern1.A", u"public.kern2.B")) + self.assertEqual(result, ("public.kern1.A", "public.kern2.B")) def test_normalizeKerningKey_validList(self): result = normalizers.normalizeKerningKey(["A", "B"]) - self.assertEqual(result, (u"A", u"B")) + self.assertEqual(result, ("A", "B")) def test_normalizeKerningKey_notTuple(self): with self.assertRaises(TypeError): @@ -198,7 +197,7 @@ def test_normalizeKerningValue_notNumber(self): def test_normalizeGroupKey_valid(self): result = normalizers.normalizeGroupKey("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeGroupKey_notString(self): with self.assertRaises(TypeError): @@ -213,11 +212,11 @@ def test_normalizeGroupKey_notLongEnough(self): def test_normalizeGroupValue_valid(self): result = normalizers.normalizeGroupValue(["A", "B", "C"]) self.assertIsInstance(result, tuple) - self.assertEqual(result, (u"A", u"B", u"C")) + self.assertEqual(result, ("A", "B", "C")) def test_normalizeGroupValue_validTuple(self): result = normalizers.normalizeGroupValue(("A", "B", "C")) - self.assertEqual(result, (u"A", u"B", u"C")) + self.assertEqual(result, ("A", "B", "C")) def test_normalizeGroupValue_validEmpty(self): result = normalizers.normalizeGroupValue([]) @@ -240,7 +239,7 @@ def test_normalizeGroupValue_invalidMember(self): def test_normalizeFeatureText_valid(self): result = normalizers.normalizeFeatureText("test") self.assertIsInstance(result, str) - self.assertEqual(result, u"test") + self.assertEqual(result, "test") def test_normalizeFeatureText_notString(self): with self.assertRaises(TypeError): @@ -255,7 +254,7 @@ def test_normalizeFeatureText_notString(self): def test_normalizeLibKey_valid(self): result = normalizers.normalizeLibKey("test") self.assertIsInstance(result, str) - self.assertEqual(result, u"test") + self.assertEqual(result, "test") def test_normalizeLibKey_notString(self): with self.assertRaises(TypeError): @@ -274,7 +273,7 @@ def test_normalizeLibValue_invalidNone(self): def test_normalizeLibValue_validString(self): result = normalizers.normalizeLibValue("test") self.assertIsInstance(result, str) - self.assertEqual(result, u"test") + self.assertEqual(result, "test") def test_normalizeLibValue_validInt(self): result = normalizers.normalizeLibValue(1) @@ -289,7 +288,7 @@ def test_normalizeLibValue_validFloat(self): def test_normalizeLibValue_validTuple(self): result = normalizers.normalizeLibValue(("A", "B")) self.assertIsInstance(result, tuple) - self.assertEqual(result, (u"A", u"B")) + self.assertEqual(result, ("A", "B")) def test_normalizeLibValue_invalidTupleMember(self): with self.assertRaises(ValueError): @@ -298,7 +297,7 @@ def test_normalizeLibValue_invalidTupleMember(self): def test_normalizeLibValue_validList(self): result = normalizers.normalizeLibValue(["A", "B"]) self.assertIsInstance(result, list) - self.assertEqual(result, [u"A", u"B"]) + self.assertEqual(result, ["A", "B"]) def test_normalizeLibValue_invalidListMember(self): with self.assertRaises(ValueError): @@ -307,7 +306,7 @@ def test_normalizeLibValue_invalidListMember(self): def test_normalizeLibValue_validDict(self): result = normalizers.normalizeLibValue({"A": 1, "B": 2}) self.assertIsInstance(result, dict) - self.assertEqual(result, {u"A": 1, u"B": 2}) + self.assertEqual(result, {"A": 1, "B": 2}) def test_normalizeLibValue_invalidDictKey(self): with self.assertRaises(TypeError): @@ -325,6 +324,7 @@ def test_normalizeLibValue_invalidDictValue(self): def test_normalizeLayer_valid(self): from fontParts.base.layer import BaseLayer + layer, _ = self.objectGenerator("layer") result = normalizers.normalizeLayer(layer) self.assertIsInstance(result, BaseLayer) @@ -339,7 +339,7 @@ def test_normalizeLayer_notLayer(self): def test_normalizeLayerName_valid(self): result = normalizers.normalizeLayerName("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeLayerName_notString(self): with self.assertRaises(TypeError): @@ -357,6 +357,7 @@ def test_normalizeLayerName_notLongEnough(self): def test_normalizeGlyph_valid(self): from fontParts.base.glyph import BaseGlyph + glyph, _ = self.objectGenerator("glyph") result = normalizers.normalizeGlyph(glyph) self.assertIsInstance(result, BaseGlyph) @@ -371,7 +372,7 @@ def test_normalizeGlyph_notGlyph(self): def test_normalizeGlyphName_valid(self): result = normalizers.normalizeGlyphName("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeGlyphName_notString(self): with self.assertRaises(TypeError): @@ -612,6 +613,7 @@ def test_normalizeGlyphFormatVersion_notNumber(self): def test_normalizeContour_valid(self): from fontParts.base.contour import BaseContour + contour, _ = self.objectGenerator("contour") result = normalizers.normalizeContour(contour) self.assertIsInstance(result, BaseContour) @@ -629,6 +631,7 @@ def test_normalizeContour_notContour(self): def test_normalizePoint_valid(self): from fontParts.base.point import BasePoint + point, _ = self.objectGenerator("point") result = normalizers.normalizePoint(point) self.assertIsInstance(result, BasePoint) @@ -643,7 +646,7 @@ def test_normalizePoint_notPoint(self): def test_normalizePointType_move(self): result = normalizers.normalizePointType("move") self.assertIsInstance(result, str) - self.assertEqual(result, u"move") + self.assertEqual(result, "move") def test_normalizePointType_Move(self): with self.assertRaises(ValueError): @@ -656,7 +659,7 @@ def test_normalizePointType_MOVE(self): def test_normalizePointType_line(self): result = normalizers.normalizePointType("line") self.assertIsInstance(result, str) - self.assertEqual(result, u"line") + self.assertEqual(result, "line") def test_normalizePointType_Line(self): with self.assertRaises(ValueError): @@ -669,7 +672,7 @@ def test_normalizePointType_LINE(self): def test_normalizePointType_offcurve(self): result = normalizers.normalizePointType("offcurve") self.assertIsInstance(result, str) - self.assertEqual(result, u"offcurve") + self.assertEqual(result, "offcurve") def test_normalizePointType_OffCurve(self): with self.assertRaises(ValueError): @@ -682,7 +685,7 @@ def test_normalizePointType_OFFCURVE(self): def test_normalizePointType_curve(self): result = normalizers.normalizePointType("curve") self.assertIsInstance(result, str) - self.assertEqual(result, u"curve") + self.assertEqual(result, "curve") def test_normalizePointType_Curve(self): with self.assertRaises(ValueError): @@ -695,7 +698,7 @@ def test_normalizePointType_CURVE(self): def test_normalizePointType_qcurve(self): result = normalizers.normalizePointType("qcurve") self.assertIsInstance(result, str) - self.assertEqual(result, u"qcurve") + self.assertEqual(result, "qcurve") def test_normalizePointType_QOffCurve(self): with self.assertRaises(ValueError): @@ -718,7 +721,7 @@ def test_normalizePointType_notString(self): def test_normalizePointName_valid(self): result = normalizers.normalizePointName("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizePointName_notString(self): with self.assertRaises(TypeError): @@ -736,6 +739,7 @@ def test_normalizePointName_notLongEnough(self): def test_normalizeSegment_valid(self): from fontParts.base.segment import BaseSegment + segment, _ = self.objectGenerator("segment") result = normalizers.normalizeSegment(segment) self.assertIsInstance(result, BaseSegment) @@ -750,7 +754,7 @@ def test_normalizePoint_notContour(self): def test_normalizeSegmentType_move(self): result = normalizers.normalizeSegmentType("move") self.assertIsInstance(result, str) - self.assertEqual(result, u"move") + self.assertEqual(result, "move") def test_normalizeSegmentType_Move(self): with self.assertRaises(ValueError): @@ -763,7 +767,7 @@ def test_normalizeSegmentType_MOVE(self): def test_normalizeSegmentType_line(self): result = normalizers.normalizeSegmentType("line") self.assertIsInstance(result, str) - self.assertEqual(result, u"line") + self.assertEqual(result, "line") def test_normalizeSegmentType_Line(self): with self.assertRaises(ValueError): @@ -776,7 +780,7 @@ def test_normalizeSegmentType_LINE(self): def test_normalizeSegmentType_curve(self): result = normalizers.normalizeSegmentType("curve") self.assertIsInstance(result, str) - self.assertEqual(result, u"curve") + self.assertEqual(result, "curve") def test_normalizeSegmentType_OffCurve(self): with self.assertRaises(ValueError): @@ -789,7 +793,7 @@ def test_normalizeSegmentType_OFFCURVE(self): def test_normalizeSegmentType_qcurve(self): result = normalizers.normalizeSegmentType("qcurve") self.assertIsInstance(result, str) - self.assertEqual(result, u"qcurve") + self.assertEqual(result, "qcurve") def test_normalizeSegmentType_QOffCurve(self): with self.assertRaises(ValueError): @@ -815,6 +819,7 @@ def test_normalizeSegmentType_notString(self): def test_normalizeBPoint_valid(self): from fontParts.base.bPoint import BaseBPoint + bPoint, _ = self.objectGenerator("bPoint") result = normalizers.normalizeBPoint(bPoint) self.assertIsInstance(result, BaseBPoint) @@ -829,7 +834,7 @@ def test_normalizeBPoint_notBPoint(self): def test_normalizeBPointType_corner(self): result = normalizers.normalizeBPointType("corner") self.assertIsInstance(result, str) - self.assertEqual(result, u"corner") + self.assertEqual(result, "corner") def test_normalizeBPointType_Corner(self): with self.assertRaises(ValueError): @@ -842,7 +847,7 @@ def test_normalizeBPointType_CORNER(self): def test_normalizeBPointType_curve(self): result = normalizers.normalizeBPointType("curve") self.assertIsInstance(result, str) - self.assertEqual(result, u"curve") + self.assertEqual(result, "curve") def test_normalizeBPointType_OffCurve(self): with self.assertRaises(ValueError): @@ -868,6 +873,7 @@ def test_normalizeBPointType_notString(self): def test_normalizeComponent_valid(self): from fontParts.base.component import BaseComponent + component, _ = self.objectGenerator("component") result = normalizers.normalizeComponent(component) self.assertIsInstance(result, BaseComponent) @@ -977,6 +983,7 @@ def test_normalizeComponentScale_tooMany(self): def test_normalizeAnchor_valid(self): from fontParts.base.anchor import BaseAnchor + anchor, _ = self.objectGenerator("anchor") result = normalizers.normalizeAnchor(anchor) self.assertIsInstance(result, BaseAnchor) @@ -991,7 +998,7 @@ def test_normalizeAnchor_notAnchor(self): def test_normalizeAnchorName_valid(self): result = normalizers.normalizeAnchorName("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeAnchorName_notString(self): with self.assertRaises(TypeError): @@ -1009,6 +1016,7 @@ def test_normalizeAnchorName_notLongEnough(self): def test_normalizeGuideline_valid(self): from fontParts.base.guideline import BaseGuideline + guideline, _ = self.objectGenerator("guideline") result = normalizers.normalizeGuideline(guideline) self.assertIsInstance(result, BaseGuideline) @@ -1023,7 +1031,7 @@ def test_normalizeGuideline_notGuideline(self): def test_normalizeGuidelineName_valid(self): result = normalizers.normalizeGuidelineName("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeGuidelineName_notString(self): with self.assertRaises(TypeError): @@ -1097,12 +1105,12 @@ def test_normalizeIdentifier_none(self): def test_normalizeIdentifier_stringMinimumLength(self): result = normalizers.normalizeIdentifier("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeIdentifier_stringMaximumLength(self): result = normalizers.normalizeIdentifier("A" * 100) self.assertIsInstance(result, str) - self.assertEqual(result, u"A" * 100) + self.assertEqual(result, "A" * 100) def test_normalizeIdentifier_stringMinimumCharacter(self): result = normalizers.normalizeIdentifier(chr(0x20)) @@ -1335,6 +1343,7 @@ def test_normalizeArea_notNumber(self): def test_normalizeColor_color(self): from fontParts.base.color import Color + result = normalizers.normalizeColor(Color((0, 0, 0, 0))) self.assertIsInstance(result, tuple) self.assertEqual(result, (0, 0, 0, 0)) @@ -1404,12 +1413,12 @@ def test_normalizeColor_invalidMember(self): def test_normalizeGlyphNote_string(self): result = normalizers.normalizeGlyphNote("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeGlyphNote_emptyString(self): result = normalizers.normalizeGlyphNote("") self.assertIsInstance(result, str) - self.assertEqual(result, u"") + self.assertEqual(result, "") def test_normalizeGlyphNote_notString(self): with self.assertRaises(TypeError): @@ -1420,12 +1429,12 @@ def test_normalizeGlyphNote_notString(self): def test_normalizeFilePath_string(self): result = normalizers.normalizeFilePath("A") self.assertIsInstance(result, str) - self.assertEqual(result, u"A") + self.assertEqual(result, "A") def test_normalizeFilePath_emptyString(self): result = normalizers.normalizeFilePath("") self.assertIsInstance(result, str) - self.assertEqual(result, u"") + self.assertEqual(result, "") def test_normalizeFilePath_notString(self): with self.assertRaises(TypeError): @@ -1621,7 +1630,9 @@ def test_normalizeTransformationMatrix_positiveInts(self): self.assertEqual(result, (1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) def test_normalizeTransformationMatrix_positiveFloats(self): - result = normalizers.normalizeTransformationMatrix((1.0, 2.0, 3.0, 4.0, 5.0, 6.0)) + result = normalizers.normalizeTransformationMatrix( + (1.0, 2.0, 3.0, 4.0, 5.0, 6.0) + ) self.assertIsInstance(result, tuple) for i in result: self.assertIsInstance(i, float) @@ -1635,8 +1646,9 @@ def test_normalizeTransformationMatrix_negativeInts(self): self.assertEqual(result, (-1.0, -2.0, -3.0, -4.0, -5.0, -6.0)) def test_normalizeTransformationMatrix_negativeFloats(self): - result = normalizers.normalizeTransformationMatrix((-1.0, -2.0, -3.0, - -4.0, -5.0, -6.0)) + result = normalizers.normalizeTransformationMatrix( + (-1.0, -2.0, -3.0, -4.0, -5.0, -6.0) + ) self.assertIsInstance(result, tuple) for i in result: self.assertIsInstance(i, float) diff --git a/Lib/fontParts/test/test_point.py b/Lib/fontParts/test/test_point.py index fd0bce26..e1251546 100644 --- a/Lib/fontParts/test/test_point.py +++ b/Lib/fontParts/test/test_point.py @@ -4,7 +4,6 @@ class TestPoint(unittest.TestCase): - def getPoint_generic(self): contour, _ = self.objectGenerator("contour") contour.appendPoint((0, 0), "move") @@ -60,10 +59,7 @@ def test_get_parent_font(self): contour = glyph.contours[0] point = contour.points[0] self.assertIsNotNone(point.font) - self.assertEqual( - point.font, - font - ) + self.assertEqual(point.font, font) def test_get_parent_noFont(self): layer, _ = self.objectGenerator("layer") @@ -84,10 +80,7 @@ def test_get_parent_layer(self): contour = glyph.contours[0] point = contour.points[0] self.assertIsNotNone(point.layer) - self.assertEqual( - point.layer, - layer - ) + self.assertEqual(point.layer, layer) def test_get_parent_noLayer(self): glyph, _ = self.objectGenerator("glyph") @@ -107,10 +100,7 @@ def test_get_parent_glyph(self): contour = glyph.contours[0] point = contour.points[0] self.assertIsNotNone(point.glyph) - self.assertEqual( - point.glyph, - glyph - ) + self.assertEqual(point.glyph, glyph) def test_get_parent_noGlyph(self): contour, _ = self.objectGenerator("contour") @@ -123,10 +113,7 @@ def test_get_parent_contour(self): contour.appendPoint((10, 20)) point = contour.points[0] self.assertIsNotNone(point.contour) - self.assertEqual( - point.contour, - contour - ) + self.assertEqual(point.contour, contour) def test_get_parent_noContour(self): point, _ = self.objectGenerator("point") @@ -142,10 +129,7 @@ def test_set_parent_contour(self): point, _ = self.objectGenerator("point") point.contour = contour self.assertIsNotNone(point.contour) - self.assertEqual( - point.contour, - contour - ) + self.assertEqual(point.contour, contour) def test_set_already_set_parent_contour(self): contour, _ = self.objectGenerator("contour") @@ -180,42 +164,27 @@ def test_get_parent_font_noContour(self): def test_get_type(self): point = self.getPoint_generic() - self.assertEqual( - point.type, - "line" - ) + self.assertEqual(point.type, "line") def test_set_move(self): point = self.getPoint_generic() point.type = "move" - self.assertEqual( - point.type, - "move" - ) + self.assertEqual(point.type, "move") def test_set_curve(self): point = self.getPoint_generic() point.type = "curve" - self.assertEqual( - point.type, - "curve" - ) + self.assertEqual(point.type, "curve") def test_set_wcurve(self): point = self.getPoint_generic() point.type = "qcurve" - self.assertEqual( - point.type, - "qcurve" - ) + self.assertEqual(point.type, "qcurve") def test_set_offcurve(self): point = self.getPoint_generic() point.type = "offcurve" - self.assertEqual( - point.type, - "offcurve" - ) + self.assertEqual(point.type, "offcurve") def test_set_invalid_point_type_string(self): point = self.getPoint_generic() @@ -231,18 +200,12 @@ def test_set_invalid_point_type_int(self): def test_get_smooth(self): point = self.getPoint_generic() - self.assertEqual( - point.smooth, - True - ) + self.assertEqual(point.smooth, True) def test_set_smooth_valid(self): point = self.getPoint_generic() point.smooth = True - self.assertEqual( - point.smooth, - True - ) + self.assertEqual(point.smooth, True) def test_set_smooth_invalid(self): point = self.getPoint_generic() @@ -253,26 +216,17 @@ def test_set_smooth_invalid(self): def test_get_x(self): point = self.getPoint_generic() - self.assertEqual( - point.x, - 101 - ) + self.assertEqual(point.x, 101) def test_set_x_valid_int(self): point = self.getPoint_generic() point.x = 100 - self.assertEqual( - point.x, - 100 - ) + self.assertEqual(point.x, 100) def test_set_x_valid_float(self): point = self.getPoint_generic() point.x = 100.5 - self.assertEqual( - point.x, - 100.5 - ) + self.assertEqual(point.x, 100.5) def test_set_x_invalidType(self): point = self.getPoint_generic() @@ -283,26 +237,17 @@ def test_set_x_invalidType(self): def test_get_y(self): point = self.getPoint_generic() - self.assertEqual( - point.y, - 202 - ) + self.assertEqual(point.y, 202) def test_set_y_valid_int(self): point = self.getPoint_generic() point.y = 200 - self.assertEqual( - point.y, - 200 - ) + self.assertEqual(point.y, 200) def test_set_y_valid_float(self): point = self.getPoint_generic() point.y = 200.5 - self.assertEqual( - point.y, - 200.5 - ) + self.assertEqual(point.y, 200.5) def test_set_y_invalidType(self): point = self.getPoint_generic() @@ -323,17 +268,11 @@ def getPoint_noParentContour(self): def test_get_index(self): point = self.getPoint_generic() - self.assertEqual( - point.index, - 1 - ) + self.assertEqual(point.index, 1) def test_get_index_noParentContour(self): point = self.getPoint_noParentContour() - self.assertEqual( - point.index, - None - ) + self.assertEqual(point.index, None) def test_set_index(self): point = self.getPoint_generic() @@ -349,33 +288,21 @@ def getPoint_withName(self): def test_get_name_noName(self): point = self.getPoint_generic() - self.assertEqual( - point.name, - None - ) + self.assertEqual(point.name, None) def test_get_name_hasName(self): point = self.getPoint_withName() - self.assertEqual( - point.name, - "P" - ) + self.assertEqual(point.name, "P") def test_set_name_valid_str(self): point = self.getPoint_generic() point.name = "P" - self.assertEqual( - point.name, - "P" - ) + self.assertEqual(point.name, "P") def test_set_name_valid_none(self): point = self.getPoint_generic() point.name = None - self.assertEqual( - point.name, - None - ) + self.assertEqual(point.name, None) def test_set_name_invalidType(self): point = self.getPoint_generic() @@ -421,41 +348,27 @@ def test_getIdentifer_consistency(self): def test_hash_object_self(self): point_one = self.getPoint_generic() - self.assertEqual( - hash(point_one), - hash(point_one) - ) + self.assertEqual(hash(point_one), hash(point_one)) def test_hash_object_other(self): point_one = self.getPoint_generic() point_two = self.getPoint_generic() - self.assertNotEqual( - hash(point_one), - hash(point_two) - ) + self.assertNotEqual(hash(point_one), hash(point_two)) def test_hash_object_self_variable_assignment(self): point_one = self.getPoint_generic() a = point_one - self.assertEqual( - hash(point_one), - hash(a) - ) + self.assertEqual(hash(point_one), hash(a)) def test_hash_object_other_variable_assignment(self): point_one = self.getPoint_generic() point_two = self.getPoint_generic() a = point_one - self.assertNotEqual( - hash(point_two), - hash(a) - ) + self.assertNotEqual(hash(point_two), hash(a)) def test_is_hashable(self): point_one = self.getPoint_generic() - self.assertTrue( - isinstance(point_one, collections.abc.Hashable) - ) + self.assertTrue(isinstance(point_one, collections.abc.Hashable)) # -------- # Equality @@ -463,35 +376,23 @@ def test_is_hashable(self): def test_object_equal_self(self): point_one = self.getPoint_generic() - self.assertEqual( - point_one, - point_one - ) + self.assertEqual(point_one, point_one) def test_object_not_equal_other(self): point_one = self.getPoint_generic() point_two = self.getPoint_generic() - self.assertNotEqual( - point_one, - point_two - ) + self.assertNotEqual(point_one, point_two) def test_object_equal_self_variable_assignment(self): point_one = self.getPoint_generic() a = point_one - self.assertEqual( - point_one, - a - ) + self.assertEqual(point_one, a) def test_object_not_equal_other_variable_assignment(self): point_one = self.getPoint_generic() point_two = self.getPoint_generic() a = point_one - self.assertNotEqual( - point_two, - a - ) + self.assertNotEqual(point_two, a) # --------- # Selection @@ -504,10 +405,7 @@ def test_selected_true(self): except NotImplementedError: return point.selected = True - self.assertEqual( - point.selected, - True - ) + self.assertEqual(point.selected, True) def test_selected_false(self): point = self.getPoint_generic() @@ -515,10 +413,7 @@ def test_selected_false(self): point.selected = False except NotImplementedError: return - self.assertEqual( - point.selected, - False - ) + self.assertEqual(point.selected, False) # ---- # Copy @@ -527,66 +422,42 @@ def test_selected_false(self): def test_copy_seperate_objects(self): point = self.getPoint_generic() copied = point.copy() - self.assertIsNot( - point, - copied - ) + self.assertIsNot(point, copied) def test_copy_different_contour(self): point = self.getPoint_generic() copied = point.copy() - self.assertIsNot( - point.contour, - copied.contour - ) + self.assertIsNot(point.contour, copied.contour) def test_copy_none_contour(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - copied.contour, - None - ) + self.assertEqual(copied.contour, None) def test_copy_same_type(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - point.type, - copied.type - ) + self.assertEqual(point.type, copied.type) def test_copy_same_smooth(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - point.smooth, - copied.smooth - ) + self.assertEqual(point.smooth, copied.smooth) def test_copy_same_x(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - point.x, - copied.x - ) + self.assertEqual(point.x, copied.x) def test_copy_same_y(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - point.y, - copied.y - ) + self.assertEqual(point.y, copied.y) def test_copy_same_name(self): point = self.getPoint_generic() copied = point.copy() - self.assertEqual( - point.name, - copied.name - ) + self.assertEqual(point.name, copied.name) def test_copy_same_identifier_None(self): point = self.getPoint_generic() @@ -613,10 +484,7 @@ def test_copy_generated_identifier_different(self): copied.contour = otherContour point.getIdentifier() copied.getIdentifier() - self.assertNotEqual( - point.identifier, - copied.identifier - ) + self.assertNotEqual(point.identifier, copied.identifier) def test_copyData_type(self): point = self.getPoint_generic() @@ -681,18 +549,12 @@ def test_copyData_different_identifier(self): def test_transformBy_valid_no_origin(self): point = self.getPoint_generic() point.transformBy((2, 0, 0, 3, -3, 2)) - self.assertEqual( - (point.x, point.y), - (199.0, 608.0) - ) + self.assertEqual((point.x, point.y), (199.0, 608.0)) def test_transformBy_valid_origin(self): point = self.getPoint_generic() point.transformBy((2, 0, 0, 2, 0, 0), origin=(1, 2)) - self.assertEqual( - (point.x, point.y), - (201.0, 402.0) - ) + self.assertEqual((point.x, point.y), (201.0, 402.0)) def test_transformBy_invalid_one_string_value(self): point = self.getPoint_generic() @@ -714,10 +576,7 @@ def test_transformBy_invalid_int_value(self): def test_moveBy_valid(self): point = self.getPoint_generic() point.moveBy((-1, 2)) - self.assertEqual( - (point.x, point.y), - (100.0, 204.0) - ) + self.assertEqual((point.x, point.y), (100.0, 204.0)) def test_moveBy_invalid_one_string_value(self): point = self.getPoint_generic() @@ -739,26 +598,17 @@ def test_moveBy_invalid_int_value(self): def test_scaleBy_valid_one_value_no_origin(self): point = self.getPoint_generic() point.scaleBy((-2)) - self.assertEqual( - (point.x, point.y), - (-202.0, -404.0) - ) + self.assertEqual((point.x, point.y), (-202.0, -404.0)) def test_scaleBy_valid_two_values_no_origin(self): point = self.getPoint_generic() point.scaleBy((-2, 3)) - self.assertEqual( - (point.x, point.y), - (-202.0, 606.0) - ) + self.assertEqual((point.x, point.y), (-202.0, 606.0)) def test_scaleBy_valid_two_values_origin(self): point = self.getPoint_generic() point.scaleBy((-2, 3), origin=(1, 2)) - self.assertEqual( - (point.x, point.y), - (-199.0, 602.0) - ) + self.assertEqual((point.x, point.y), (-199.0, 602.0)) def test_scaleBy_invalid_one_string_value(self): point = self.getPoint_generic() @@ -780,18 +630,12 @@ def test_scaleBy_invalid_tuple_too_many_values(self): def test_rotateBy_valid_no_origin(self): point = self.getPoint_generic() point.rotateBy(45) - self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-71.418, 214.253] - ) + self.assertEqual([(round(point.x, 3)), (round(point.y, 3))], [-71.418, 214.253]) def test_rotateBy_valid_origin(self): point = self.getPoint_generic() point.rotateBy(45, origin=(1, 2)) - self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-69.711, 214.132] - ) + self.assertEqual([(round(point.x, 3)), (round(point.y, 3))], [-69.711, 214.132]) def test_rotateBy_invalid_string_value(self): point = self.getPoint_generic() @@ -813,33 +657,25 @@ def test_rotateBy_invalid_too_large_value_negative(self): def test_skewBy_valid_no_origin_one_value(self): point = self.getPoint_generic() point.skewBy(100) - self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-1044.599, 202.0] - ) + self.assertEqual([(round(point.x, 3)), (round(point.y, 3))], [-1044.599, 202.0]) def test_skewBy_valid_no_origin_two_values(self): point = self.getPoint_generic() point.skewBy((100, 200)) self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-1044.599, 238.761] + [(round(point.x, 3)), (round(point.y, 3))], [-1044.599, 238.761] ) def test_skewBy_valid_origin_one_value(self): point = self.getPoint_generic() point.skewBy(100, origin=(1, 2)) - self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-1033.256, 202.0] - ) + self.assertEqual([(round(point.x, 3)), (round(point.y, 3))], [-1033.256, 202.0]) def test_skewBy_valid_origin_two_values(self): point = self.getPoint_generic() point.skewBy((100, 200), origin=(1, 2)) self.assertEqual( - [(round(point.x, 3)), (round(point.y, 3))], - [-1033.256, 238.397] + [(round(point.x, 3)), (round(point.y, 3))], [-1033.256, 238.397] ) # ------------- @@ -857,15 +693,9 @@ def getPoint_floatXY(self): def test_roundX(self): point = self.getPoint_floatXY() point.round() - self.assertEqual( - point.x, - 101 - ) + self.assertEqual(point.x, 101) def test_roundY(self): point = self.getPoint_floatXY() point.round() - self.assertEqual( - point.y, - 203 - ) + self.assertEqual(point.y, 203) diff --git a/Lib/fontParts/test/test_segment.py b/Lib/fontParts/test/test_segment.py index 5a402969..61a9ee2c 100644 --- a/Lib/fontParts/test/test_segment.py +++ b/Lib/fontParts/test/test_segment.py @@ -3,7 +3,6 @@ class TestSegment(unittest.TestCase): - def getSegment_line(self): contour, unrequested = self.objectGenerator("contour") unrequested.append(contour) @@ -18,110 +17,71 @@ def getSegment_line(self): def test_type_get(self): segment = self.getSegment_line() - self.assertEqual( - segment.type, - "line" - ) + self.assertEqual(segment.type, "line") def test_set_move(self): segment = self.getSegment_line() segment.type = "move" - self.assertEqual( - segment.type, - "move" - ) + self.assertEqual(segment.type, "move") def test_len_move(self): segment = self.getSegment_line() segment.type = "move" - self.assertEqual( - len(segment.points), - 1 - ) + self.assertEqual(len(segment.points), 1) def test_oncuve_type_move(self): segment = self.getSegment_line() segment.type = "move" - self.assertEqual( - segment.onCurve.type, - "move" - ) + self.assertEqual(segment.onCurve.type, "move") def test_oncuve_x_y(self): segment = self.getSegment_line() segment.type = "move" - self.assertEqual( - (segment.onCurve.x, segment.onCurve.y), - (101, 202) - ) + self.assertEqual((segment.onCurve.x, segment.onCurve.y), (101, 202)) def test_set_curve(self): segment = self.getSegment_line() segment.type = "curve" - self.assertEqual( - segment.type, - "curve" - ) + self.assertEqual(segment.type, "curve") def test_len_curve(self): segment = self.getSegment_line() segment.type = "curve" - self.assertEqual( - len(segment.points), - 3 - ) + self.assertEqual(len(segment.points), 3) def test_curve_pt_types(self): segment = self.getSegment_line() segment.type = "curve" types = tuple(point.type for point in segment.points) - self.assertEqual( - types, - ("offcurve", "offcurve", "curve") - ) + self.assertEqual(types, ("offcurve", "offcurve", "curve")) def test_curve_pt_x_y(self): segment = self.getSegment_line() segment.type = "curve" coordinates = tuple((point.x, point.y) for point in segment.points) - self.assertEqual( - coordinates, - ((0, 0), (101, 202), (101, 202)) - ) + self.assertEqual(coordinates, ((0, 0), (101, 202), (101, 202))) def test_set_qcurve(self): segment = self.getSegment_line() segment.type = "qcurve" - self.assertEqual( - segment.type, - "qcurve" - ) + self.assertEqual(segment.type, "qcurve") def test_len_qcurve(self): segment = self.getSegment_line() segment.type = "qcurve" - self.assertEqual( - len(segment.points), - 3 - ) + self.assertEqual(len(segment.points), 3) def test_qcurve_pt_types(self): segment = self.getSegment_line() segment.type = "qcurve" types = tuple(point.type for point in segment.points) - self.assertEqual( - types, - ("offcurve", "offcurve", "qcurve") - ) + self.assertEqual(types, ("offcurve", "offcurve", "qcurve")) def test_qcurve_pt_x_y(self): segment = self.getSegment_line() segment.type = "qcurve" coordinates = tuple((point.x, point.y) for point in segment.points) - self.assertEqual( - coordinates, - ((0, 0), (101, 202), (101, 202)) - ) + self.assertEqual(coordinates, ((0, 0), (101, 202), (101, 202))) def test_set_invalid_segment_type_string(self): segment = self.getSegment_line() @@ -141,23 +101,13 @@ def test_offCurve_only_segment(self): contour.appendPoint((100, 100), "offcurve") contour.appendPoint((0, 100), "offcurve") segment = contour[0] - self.assertEqual( - len(contour), - 1 - ) + self.assertEqual(len(contour), 1) # onCurve is a dummy None value, telling this is an on-curve-less quad blob self.assertIsNone( segment.onCurve, ) - self.assertEqual( - segment.points, - segment.offCurve - ) - self.assertEqual( - segment.type, - "qcurve" - ) - + self.assertEqual(segment.points, segment.offCurve) + self.assertEqual(segment.type, "qcurve") # ---- # Hash @@ -165,10 +115,7 @@ def test_offCurve_only_segment(self): def test_hash(self): segment = self.getSegment_line() - self.assertEqual( - isinstance(segment, collections.abc.Hashable), - False - ) + self.assertEqual(isinstance(segment, collections.abc.Hashable), False) # -------- # Equality @@ -176,35 +123,23 @@ def test_hash(self): def test_object_equal_self(self): segment_one = self.getSegment_line() - self.assertEqual( - segment_one, - segment_one - ) + self.assertEqual(segment_one, segment_one) def test_object_not_equal_other(self): segment_one = self.getSegment_line() segment_two = self.getSegment_line() - self.assertNotEqual( - segment_one, - segment_two - ) + self.assertNotEqual(segment_one, segment_two) def test_object_equal_self_variable_assignment(self): segment_one = self.getSegment_line() a = segment_one - self.assertEqual( - segment_one, - a - ) + self.assertEqual(segment_one, a) def test_object_not_equal_other_variable_assignment(self): segment_one = self.getSegment_line() segment_two = self.getSegment_line() a = segment_one - self.assertNotEqual( - segment_two, - a - ) + self.assertNotEqual(segment_two, a) # --------- # Selection @@ -217,10 +152,7 @@ def test_selected_true(self): except NotImplementedError: return segment.selected = True - self.assertEqual( - segment.selected, - True - ) + self.assertEqual(segment.selected, True) def test_selected_false(self): segment = self.getSegment_line() @@ -228,7 +160,4 @@ def test_selected_false(self): segment.selected = False except NotImplementedError: return - self.assertEqual( - segment.selected, - False - ) + self.assertEqual(segment.selected, False) diff --git a/Lib/fontParts/test/test_world.py b/Lib/fontParts/test/test_world.py index e9f1a63e..21ab6d0b 100644 --- a/Lib/fontParts/test/test_world.py +++ b/Lib/fontParts/test/test_world.py @@ -3,8 +3,8 @@ import os from fontParts.world import RFont, FontList, OpenFont, OpenFonts -class TestFontList(unittest.TestCase): +class TestFontList(unittest.TestCase): def getFont(self): font, _ = self.objectGenerator("font") return font @@ -47,10 +47,7 @@ def getFont_sortBy_proportionalGlyphs(self): # familyName def test_sortBy_familyName(self): - fonts = self.getFonts_sortBy( - "familyName", - ["aaa", "bbb", "ccc", None] - ) + fonts = self.getFonts_sortBy("familyName", ["aaa", "bbb", "ccc", None]) font1, font2, font3, font4 = fonts fonts.sortBy("familyName") expected = [font4, font1, font2, font3] @@ -59,10 +56,7 @@ def test_sortBy_familyName(self): # styleName def test_sortBy_styleName(self): - fonts = self.getFonts_sortBy( - "styleName", - ["aaa", "bbb", "ccc", None] - ) + fonts = self.getFonts_sortBy("styleName", ["aaa", "bbb", "ccc", None]) font1, font2, font3, font4 = fonts fonts.sortBy("styleName") expected = [font4, font1, font2, font3] @@ -72,8 +66,7 @@ def test_sortBy_styleName(self): def test_sortBy_isRoman_styleMapStyleName(self): fonts = self.getFonts_sortBy( - "styleMapStyleName", - ["regular", "italic", "bold", "bold italic"] + "styleMapStyleName", ["regular", "italic", "bold", "bold italic"] ) font1, font2, font3, font4 = fonts fonts.reverse() @@ -82,10 +75,7 @@ def test_sortBy_isRoman_styleMapStyleName(self): self.assertEqual(fonts, expected) def test_sortBy_isRoman_italicAngle(self): - fonts = self.getFonts_sortBy( - "italicAngle", - [1, 2, 3, 0] - ) + fonts = self.getFonts_sortBy("italicAngle", [1, 2, 3, 0]) font1, font2, font3, font4 = fonts fonts.sortBy("isRoman") expected = [font4, font1, font2, font3] @@ -95,8 +85,7 @@ def test_sortBy_isRoman_italicAngle(self): def test_sortBy_isItalic_styleMapStyleName(self): fonts = self.getFonts_sortBy( - "styleMapStyleName", - ["regular", "italic", "bold", "bold italic"] + "styleMapStyleName", ["regular", "italic", "bold", "bold italic"] ) font1, font2, font3, font4 = fonts fonts.sortBy("isItalic") @@ -104,10 +93,7 @@ def test_sortBy_isItalic_styleMapStyleName(self): self.assertEqual(fonts, expected) def test_sortBy_isItalic_italicAngle(self): - fonts = self.getFonts_sortBy( - "italicAngle", - [0, 1, 2, 3] - ) + fonts = self.getFonts_sortBy("italicAngle", [0, 1, 2, 3]) font1, font2, font3, font4 = fonts fonts.sortBy("isItalic") expected = [font2, font3, font4, font1] @@ -116,10 +102,7 @@ def test_sortBy_isItalic_italicAngle(self): # widthValue def test_sortBy_widthValue(self): - fonts = self.getFonts_sortBy( - "openTypeOS2WidthClass", - [1, 2, 3, None] - ) + fonts = self.getFonts_sortBy("openTypeOS2WidthClass", [1, 2, 3, None]) font1, font2, font3, font4 = fonts fonts.sortBy("widthValue") expected = [font4, font1, font2, font3] @@ -128,10 +111,7 @@ def test_sortBy_widthValue(self): # weightValue def test_sortBy_weightValue(self): - fonts = self.getFonts_sortBy( - "openTypeOS2WeightClass", - [100, 200, 300, None] - ) + fonts = self.getFonts_sortBy("openTypeOS2WeightClass", [100, 200, 300, None]) font1, font2, font3, font4 = fonts fonts.sortBy("weightValue") expected = [font4, font1, font2, font3] @@ -141,8 +121,7 @@ def test_sortBy_weightValue(self): def test_sortBy_isMonospace_postscriptIsFixedPitch(self): fonts = self.getFonts_sortBy( - "postscriptIsFixedPitch", - [True, True, False, False] + "postscriptIsFixedPitch", [True, True, False, False] ) font1, font2, font3, font4 = fonts fonts.reverse() @@ -166,8 +145,7 @@ def test_sortBy_isMonospace_glyphs(self): def test_sortBy_isProportional_postscriptIsFixedPitch(self): fonts = self.getFonts_sortBy( - "postscriptIsFixedPitch", - [False, False, True, True] + "postscriptIsFixedPitch", [False, False, True, True] ) font1, font2, font3, font4 = fonts fonts.reverse() @@ -189,10 +167,7 @@ def test_sortBy_isProportional_glyphs(self): # font.info Attributes def test_sortBy_fontInfoAttribute_xHeight(self): - fonts = self.getFonts_sortBy( - "xHeight", - [10, 20, 30, 40] - ) + fonts = self.getFonts_sortBy("xHeight", [10, 20, 30, 40]) font1, font2, font3, font4 = fonts fonts.reverse() fonts.sortBy("xHeight") @@ -217,13 +192,14 @@ def test_sortBy_sortValueFunction(self): fonts = FontList() fonts.extend([font1, font2, font3, font4]) fonts.reverse() + def glyphCountSortValue(font): return len(font) + fonts.sortBy(glyphCountSortValue) expected = [font1, font2, font3, font4] self.assertEqual(fonts, expected) - # ------ # Search # ------ @@ -280,8 +256,8 @@ def test_getFontsByFamilyNameStyleName(self): found = fonts.getFontsByFamilyNameStyleName("A", "1") self.assertEqual(found, [font1, font4]) -class TestFontOpen(unittest.TestCase): +class TestFontOpen(unittest.TestCase): def setUp(self): font, _ = self.objectGenerator("font") self.font_dir = tempfile.mkdtemp() @@ -290,6 +266,7 @@ def setUp(self): def tearDown(self): import shutil + shutil.rmtree(self.font_dir) def test_font_open(self): @@ -297,7 +274,6 @@ def test_font_open(self): class TestOpenFonts(unittest.TestCase): - def setUp(self): self.font_dir = tempfile.mkdtemp() for i in range(3): @@ -307,6 +283,7 @@ def setUp(self): def tearDown(self): import shutil + shutil.rmtree(self.font_dir) def test_font_open(self): @@ -318,6 +295,5 @@ def test_font_open(self): class TestFontShell_RFont(unittest.TestCase): - def test_fontshell_RFont_empty(self): RFont() diff --git a/Lib/fontParts/ui.py b/Lib/fontParts/ui.py index fe2746db..c88a9afb 100644 --- a/Lib/fontParts/ui.py +++ b/Lib/fontParts/ui.py @@ -1,7 +1,7 @@ from fontParts.world import _EnvironmentDispatcher -def AskString(message, value='', title='FontParts'): +def AskString(message, value="", title="FontParts"): """ An ask a string dialog, a `message` is required. Optionally a `value` and `title` can be provided. @@ -9,13 +9,14 @@ def AskString(message, value='', title='FontParts'): :: from fontParts.ui import AskString + print(AskString("who are you?")) """ return dispatcher["AskString"](message=message, value=value, title=title) -def AskYesNoCancel(message, title='FontParts', default=0, informativeText=""): +def AskYesNoCancel(message, title="FontParts", default=0, informativeText=""): """ An ask yes, no or cancel dialog, a `message` is required. Optionally a `title`, `default` and `informativeText` can be provided. @@ -24,14 +25,16 @@ def AskYesNoCancel(message, title='FontParts', default=0, informativeText=""): :: from fontParts.ui import AskYesNoCancel + print(AskYesNoCancel("who are you?")) """ - return dispatcher["AskYesNoCancel"](message=message, title=title, - default=default, informativeText=informativeText) + return dispatcher["AskYesNoCancel"]( + message=message, title=title, default=default, informativeText=informativeText + ) -def FindGlyph(aFont, message="Search for a glyph:", title='FontParts'): +def FindGlyph(aFont, message="Search for a glyph:", title="FontParts"): """ A dialog to search a glyph for a provided font. Optionally a `message`, `title` and `allFonts` can be provided. @@ -46,8 +49,14 @@ def FindGlyph(aFont, message="Search for a glyph:", title='FontParts'): return dispatcher["FindGlyph"](aFont=aFont, message=message, title=title) -def GetFile(message=None, title=None, directory=None, fileName=None, - allowsMultipleSelection=False, fileTypes=None): +def GetFile( + message=None, + title=None, + directory=None, + fileName=None, + allowsMultipleSelection=False, + fileTypes=None, +): """ An get file dialog. Optionally a `message`, `title`, `directory`, `fileName` and @@ -56,17 +65,28 @@ def GetFile(message=None, title=None, directory=None, fileName=None, :: from fontParts.ui import GetFile + print(GetFile()) """ - return dispatcher["GetFile"](message=message, title=title, directory=directory, - fileName=fileName, - allowsMultipleSelection=allowsMultipleSelection, - fileTypes=fileTypes) + return dispatcher["GetFile"]( + message=message, + title=title, + directory=directory, + fileName=fileName, + allowsMultipleSelection=allowsMultipleSelection, + fileTypes=fileTypes, + ) -def GetFileOrFolder(message=None, title=None, directory=None, fileName=None, - allowsMultipleSelection=False, fileTypes=None): +def GetFileOrFolder( + message=None, + title=None, + directory=None, + fileName=None, + allowsMultipleSelection=False, + fileTypes=None, +): """ An get file or folder dialog. Optionally a `message`, `title`, `directory`, `fileName`, @@ -75,16 +95,21 @@ def GetFileOrFolder(message=None, title=None, directory=None, fileName=None, :: from fontParts.ui import GetFileOrFolder + print(GetFileOrFolder()) """ - return dispatcher["GetFileOrFolder"](message=message, title=title, - directory=directory, fileName=fileName, - allowsMultipleSelection=allowsMultipleSelection, - fileTypes=fileTypes) + return dispatcher["GetFileOrFolder"]( + message=message, + title=title, + directory=directory, + fileName=fileName, + allowsMultipleSelection=allowsMultipleSelection, + fileTypes=fileTypes, + ) -def Message(message, title='FontParts', informativeText=""): +def Message(message, title="FontParts", informativeText=""): """ An message dialog. Optionally a `message`, `title` and `informativeText` can be provided. @@ -92,11 +117,13 @@ def Message(message, title='FontParts', informativeText=""): :: from fontParts.ui import Message + print(Message("This is a message")) """ - return dispatcher["Message"](message=message, title=title, - informativeText=informativeText) + return dispatcher["Message"]( + message=message, title=title, informativeText=informativeText + ) def PutFile(message=None, fileName=None): @@ -107,13 +134,14 @@ def PutFile(message=None, fileName=None): :: from fontParts.ui import PutFile + print(PutFile()) """ return dispatcher["PutFile"](message=message, fileName=fileName) -def SearchList(items, message="Select an item:", title='FontParts'): +def SearchList(items, message="Select an item:", title="FontParts"): """ A dialgo to search a given list. Optionally a `message`, `title` and `allFonts` can be provided. @@ -121,6 +149,7 @@ def SearchList(items, message="Select an item:", title='FontParts'): :: from fontParts.ui import SearchList + result = SearchList(["a", "b", "c"]) print(result) @@ -128,7 +157,7 @@ def SearchList(items, message="Select an item:", title='FontParts'): return dispatcher["SearchList"](items=items, message=message, title=title) -def SelectFont(message="Select a font:", title='FontParts', allFonts=None): +def SelectFont(message="Select a font:", title="FontParts", allFonts=None): """ Select a font from all open fonts. Optionally a `message`, `title` and `allFonts` can be provided. @@ -137,6 +166,7 @@ def SelectFont(message="Select a font:", title='FontParts', allFonts=None): :: from fontParts.ui import SelectFont + font = SelectFont() print(font) @@ -144,7 +174,7 @@ def SelectFont(message="Select a font:", title='FontParts', allFonts=None): return dispatcher["SelectFont"](message=message, title=title, allFonts=allFonts) -def SelectGlyph(aFont, message="Select a glyph:", title='FontParts'): +def SelectGlyph(aFont, message="Select a glyph:", title="FontParts"): """ Select a glyph for a given font. Optionally a `message` and `title` can be provided. @@ -152,6 +182,7 @@ def SelectGlyph(aFont, message="Select a glyph:", title='FontParts'): :: from fontParts.ui import SelectGlyph + font = CurrentFont() glyph = SelectGlyph(font) print(glyph) @@ -181,18 +212,20 @@ def ProgressBar(title="RoboFab...", ticks=None, label=""): # Dispatcher # ---------- -dispatcher = _EnvironmentDispatcher([ - "AskString", - "AskYesNoCancel", - "FindGlyph", - "GetFile", - "GetFolder", - "GetFileOrFolder", - "Message", - "OneList", - "PutFile", - "SearchList", - "SelectFont", - "SelectGlyph", - "ProgressBar", -]) +dispatcher = _EnvironmentDispatcher( + [ + "AskString", + "AskYesNoCancel", + "FindGlyph", + "GetFile", + "GetFolder", + "GetFileOrFolder", + "Message", + "OneList", + "PutFile", + "SearchList", + "SelectFont", + "SelectGlyph", + "ProgressBar", + ] +) diff --git a/Lib/fontParts/world.py b/Lib/fontParts/world.py index d0ddd50f..05ad43da 100644 --- a/Lib/fontParts/world.py +++ b/Lib/fontParts/world.py @@ -1,6 +1,7 @@ import os import glob + def OpenFonts(directory=None, showInterface=True, fileExtensions=None): """ Open all fonts with the given **fileExtensions** located in @@ -24,6 +25,7 @@ def OpenFonts(directory=None, showInterface=True, fileExtensions=None): fonts = OpenFonts(showInterface=False) """ from fontParts.ui import GetFileOrFolder + if fileExtensions is None: fileExtensions = dispatcher["OpenFontsFileExtensions"] if isinstance(directory, str): @@ -84,8 +86,9 @@ def NewFont(familyName=None, styleName=None, showInterface=True): font = NewFont(familyName="My Family", styleName="My Style") font = NewFont(showInterface=False) """ - return dispatcher["NewFont"](familyName=familyName, styleName=styleName, - showInterface=showInterface) + return dispatcher["NewFont"]( + familyName=familyName, styleName=styleName, showInterface=showInterface + ) def CurrentFont(): @@ -304,6 +307,7 @@ def RGlyph(): # Font List # --------- + def FontList(fonts=None): """ Get a list with font specific methods. @@ -323,7 +327,6 @@ def FontList(fonts=None): class BaseFontList(list): - # Sort def sortBy(self, sortOptions, reverse=False): @@ -416,6 +419,7 @@ def sortBy(self, sortOptions, reverse=False): >>> fonts.sortBy("magic") """ from types import FunctionType + valueGetters = dict( familyName=_sortValue_familyName, styleName=_sortValue_styleName, @@ -424,7 +428,7 @@ def sortBy(self, sortOptions, reverse=False): widthValue=_sortValue_widthValue, weightValue=_sortValue_weightValue, isProportional=_sortValue_isProportional, - isMonospace=_sortValue_isMonospace + isMonospace=_sortValue_isMonospace, ) if isinstance(sortOptions, str) or isinstance(sortOptions, FunctionType): sortOptions = [sortOptions] @@ -439,7 +443,7 @@ def sortBy(self, sortOptions, reverse=False): "widthValue", "weightValue", "styleName", - "isRoman" + "isRoman", ] sorter = [] for originalIndex, font in enumerate(self): @@ -510,7 +514,9 @@ def getFontsByFamilyNameStyleName(self, familyName, styleName): Get a list of fonts that match ``familyName`` and ``styleName``. This will return an instance of :class:`BaseFontList`. """ - return self.getFontsByFontInfoAttribute(("familyName", familyName), ("styleName", styleName)) + return self.getFontsByFontInfoAttribute( + ("familyName", familyName), ("styleName", styleName) + ) def _sortValue_familyName(font): @@ -612,8 +618,8 @@ def _sortValue_isMonospace(font): # Dispatcher # ---------- -class _EnvironmentDispatcher(object): +class _EnvironmentDispatcher(object): def __init__(self, registryItems): self._registry = {item: None for item in registryItems} @@ -627,37 +633,38 @@ def __getitem__(self, name): return func -dispatcher = _EnvironmentDispatcher([ - "OpenFontsFileExtensions", - "OpenFont", - "NewFont", - "AllFonts", - "CurrentFont", - "CurrentGlyph", - "CurrentLayer", - "CurrentContours", - "CurrentSegments", - "CurrentPoints", - "CurrentComponents", - "CurrentAnchors", - "CurrentGuidelines", - "FontList", - "RFont", - "RLayer", - "RGlyph", - "RContour", - "RPoint", - "RAnchor", - "RComponent", - "RGuideline", - "RImage", - "RInfo", - "RFeatures", - "RGroups", - "RKerning", - "RLib", - -]) +dispatcher = _EnvironmentDispatcher( + [ + "OpenFontsFileExtensions", + "OpenFont", + "NewFont", + "AllFonts", + "CurrentFont", + "CurrentGlyph", + "CurrentLayer", + "CurrentContours", + "CurrentSegments", + "CurrentPoints", + "CurrentComponents", + "CurrentAnchors", + "CurrentGuidelines", + "FontList", + "RFont", + "RLayer", + "RGlyph", + "RContour", + "RPoint", + "RAnchor", + "RComponent", + "RGuideline", + "RImage", + "RInfo", + "RFeatures", + "RGroups", + "RKerning", + "RLib", + ] +) # Register the default functions. diff --git a/documentation/source/_themes/fontPartsTheme/static/sass2css.py b/documentation/source/_themes/fontPartsTheme/static/sass2css.py index 9ad24c71..3136f1b7 100644 --- a/documentation/source/_themes/fontPartsTheme/static/sass2css.py +++ b/documentation/source/_themes/fontPartsTheme/static/sass2css.py @@ -11,11 +11,12 @@ ## npm install -g postcss-cli-simple ## npm install -g autoprefixer + def compileSass(sassPath): - ''' + """ Compile a sass file (and dependencies) into a single css file. - ''' + """ cssPath = os.path.splitext(sassPath)[0] + ".css" # subprocess.call(["sass", sassPath, cssPath]) print("Compiling Sass") @@ -23,16 +24,23 @@ def compileSass(sassPath): process = subprocess.Popen(["sass", sassPath, cssPath]) process.wait() + def autoprefixCSS(sassPath): - ''' + """ Take CSS file and automatically add browser prefixes with postCSS autoprefixer - ''' + """ print("Autoprefixing CSS") cssPath = os.path.splitext(sassPath)[0] + ".css" - command = "postcss --use autoprefixer --autoprefixer.browsers '> 5%' -o" + cssPath + " " + cssPath + command = ( + "postcss --use autoprefixer --autoprefixer.browsers '> 5%' -o" + + cssPath + + " " + + cssPath + ) subprocess.call(command, shell=True) + # gets path for directory of sass2css.py baseFolder = os.path.split(os.path.abspath(__file__))[0] diff --git a/documentation/source/conf.py b/documentation/source/conf.py index a75b5ffa..97c6a9b2 100644 --- a/documentation/source/conf.py +++ b/documentation/source/conf.py @@ -15,7 +15,7 @@ import sys import os -sys.path.insert(0, os.path.abspath('../../Lib')) +sys.path.insert(0, os.path.abspath("../../Lib")) # ------------ # Mock Imports @@ -36,15 +36,15 @@ def __getattr__(cls, name): return Mock() MOCK_MODULES = [ - 'fontTools', - 'fontTools.misc', - 'fontTools.misc.py23', - 'fontTools.pens', - 'fontTools.pens.basePen', - 'fontMath', - 'ufoLib', - 'ufoLib.pointPen', - 'defcon' + "fontTools", + "fontTools.misc", + "fontTools.misc.py23", + "fontTools.pens", + "fontTools.pens.basePen", + "fontMath", + "ufoLib", + "ufoLib.pointPen", + "defcon", ] sys.modules.update((mod_name, Mock()) for mod_name in MOCK_MODULES) @@ -57,6 +57,7 @@ def __getattr__(cls, name): # https://github.com/sphinx-doc/sphinx/issues/1254 # from fontParts.base.base import dynamicProperty + dynamicProperty.__get__ = lambda self, *args, **kwargs: self # # /MonkeyPatch @@ -65,61 +66,59 @@ def __getattr__(cls, name): # If extensions (or modules to document with autodoc) are in another directory, # add these directories to sys.path here. If the directory is relative to the # documentation root, use os.path.abspath to make it absolute, like shown here. -#sys.path.insert(0, os.path.abspath('.')) +# sys.path.insert(0, os.path.abspath('.')) # -- General configuration ------------------------------------------------ # If your documentation needs a minimal Sphinx version, state it here. -#needs_sphinx = '1.0' +# needs_sphinx = '1.0' # Add any Sphinx extension module names here, as strings. They can be # extensions coming with Sphinx (named 'sphinx.ext.*') or your custom # ones. extensions = [ - 'sphinx.ext.intersphinx', - 'sphinx.ext.autodoc', - 'sphinx.ext.todo', - 'sphinx.ext.coverage', - 'sphinx.ext.ifconfig', - 'sphinx.ext.viewcode', - 'sphinx.ext.autosummary', + "sphinx.ext.intersphinx", + "sphinx.ext.autodoc", + "sphinx.ext.todo", + "sphinx.ext.coverage", + "sphinx.ext.ifconfig", + "sphinx.ext.viewcode", + "sphinx.ext.autosummary", ] -intersphinx_mapping = { - 'python': ('https://docs.python.org/3/', None) -} +intersphinx_mapping = {"python": ("https://docs.python.org/3/", None)} -autodoc_member_order = 'bysource' -autoclass_content = 'both' +autodoc_member_order = "bysource" +autoclass_content = "both" # Add any paths that contain templates here, relative to this directory. -templates_path = ['_templates'] +templates_path = ["_templates"] # The suffix(es) of source filenames. # You can specify multiple suffix as a list of string: # source_suffix = ['.rst', '.md'] -source_suffix = '.rst' +source_suffix = ".rst" # The encoding of source files. -#source_encoding = 'utf-8-sig' +# source_encoding = 'utf-8-sig' # The master toctree document. -master_doc = 'contents' # was 'index' +master_doc = "contents" # was 'index' # General information about the project. -project = u'FontParts' -copyright = u'2016, Dr. Rob O. Fab' -author = u'Dr. Rob O. Fab' +project = "FontParts" +copyright = "2016, Dr. Rob O. Fab" +author = "Dr. Rob O. Fab" # The version info for the project you're documenting, acts as replacement for # |version| and |release|, also used in various other places throughout the # built documents. # # The short X.Y version. -version = u'0.1' +version = "0.1" # The full version, including alpha/beta/rc tags. -release = u'0.1' +release = "0.1" # The language for content autogenerated by Sphinx. Refer to documentation # for a list of supported languages. @@ -130,9 +129,9 @@ def __getattr__(cls, name): # There are two options for replacing |today|: either, you set today to some # non-false value, then it is used: -#today = '' +# today = '' # Else, today_fmt is used as the format for a strftime call. -#today_fmt = '%B %d, %Y' +# today_fmt = '%B %d, %Y' # List of patterns, relative to source directory, that match files and # directories to ignore when looking for source files. @@ -140,27 +139,27 @@ def __getattr__(cls, name): # The reST default role (used for this markup: `text`) to use for all # documents. -#default_role = None +# default_role = None # If true, '()' will be appended to :func: etc. cross-reference text. add_function_parentheses = False # If true, the current module name will be prepended to all description # unit titles (such as .. function::). -#add_module_names = True +# add_module_names = True # If true, sectionauthor and moduleauthor directives will be shown in the # output. They are ignored by default. -#show_authors = False +# show_authors = False # The name of the Pygments (syntax highlighting) style to use. -pygments_style = 'sphinx' +pygments_style = "sphinx" # A list of ignored prefixes for module index sorting. -#modindex_common_prefix = [] +# modindex_common_prefix = [] # If true, keep warnings as "system message" paragraphs in the built documents. -#keep_warnings = False +# keep_warnings = False # If true, `todo` and `todoList` produce output, else they produce nothing. todo_include_todos = True @@ -170,157 +169,156 @@ def __getattr__(cls, name): # The theme to use for HTML and HTML Help pages. See the documentation for # a list of builtin themes. -html_theme = 'fontPartsTheme' +html_theme = "fontPartsTheme" # Theme options are theme-specific and customize the look and feel of a theme # further. For a list of options available for each theme, see the # documentation. -#html_theme_options = {} +# html_theme_options = {} # Add any paths that contain custom themes here, relative to this directory. -sys.path.append(os.path.abspath('_themes')) -html_theme_path = ['_themes'] +sys.path.append(os.path.abspath("_themes")) +html_theme_path = ["_themes"] # The name for this set of Sphinx documents. If None, it defaults to # " v documentation". -#html_title = None +# html_title = None # A shorter title for the navigation bar. Default is the same as html_title. -#html_short_title = None +# html_short_title = None # The name of an image file (relative to this directory) to place at the top # of the sidebar. -#html_logo = None +# html_logo = None # The name of an image file (relative to this directory) to use as a favicon of # the docs. This file should be a Windows icon file (.ico) being 16x16 or 32x32 # pixels large. -#html_favicon = None +# html_favicon = None # Add any paths that contain custom static files (such as style sheets) here, # relative to this directory. They are copied after the builtin static files, # so a file named "default.css" will overwrite the builtin "default.css". -html_static_path = ['_static'] +html_static_path = ["_static"] # Add any extra paths that contain custom files (such as robots.txt or # .htaccess) here, relative to this directory. These files are copied # directly to the root of the documentation. -#html_extra_path = [] +# html_extra_path = [] # If not '', a 'Last updated on:' timestamp is inserted at every page bottom, # using the given strftime format. -#html_last_updated_fmt = '%b %d, %Y' +# html_last_updated_fmt = '%b %d, %Y' # If true, SmartyPants will be used to convert quotes and dashes to # typographically correct entities. -#html_use_smartypants = True +# html_use_smartypants = True # Custom sidebar templates, maps document names to template names. -#html_sidebars = {} +# html_sidebars = {} # Additional templates that should be rendered to pages, maps page names to # template names. -#html_additional_pages = {} +# html_additional_pages = {} # If false, no module index is generated. -#html_domain_indices = True +# html_domain_indices = True # If false, no index is generated. -#html_use_index = True +# html_use_index = True # If true, the index is split into individual pages for each letter. -#html_split_index = False +# html_split_index = False # If true, links to the reST sources are added to the pages. -#html_show_sourcelink = True +# html_show_sourcelink = True # If true, "Created using Sphinx" is shown in the HTML footer. Default is True. -#html_show_sphinx = True +# html_show_sphinx = True # If true, "(C) Copyright ..." is shown in the HTML footer. Default is True. -#html_show_copyright = True +# html_show_copyright = True # If true, an OpenSearch description file will be output, and all pages will # contain a tag referring to it. The value of this option must be the # base URL from which the finished HTML is served. -#html_use_opensearch = '' +# html_use_opensearch = '' # This is the file name suffix for HTML files (e.g. ".xhtml"). -#html_file_suffix = None +# html_file_suffix = None # Language to be used for generating the HTML full-text search index. # Sphinx supports the following languages: # 'da', 'de', 'en', 'es', 'fi', 'fr', 'hu', 'it', 'ja' # 'nl', 'no', 'pt', 'ro', 'ru', 'sv', 'tr' -#html_search_language = 'en' +# html_search_language = 'en' # A dictionary with options for the search language support, empty by default. # Now only 'ja' uses this config value -#html_search_options = {'type': 'default'} +# html_search_options = {'type': 'default'} # The name of a javascript file (relative to the configuration directory) that # implements a search results scorer. If empty, the default will be used. -#html_search_scorer = 'scorer.js' +# html_search_scorer = 'scorer.js' # Output file base name for HTML help builder. -htmlhelp_basename = 'FontPartsdoc' +htmlhelp_basename = "FontPartsdoc" # -- Options for LaTeX output --------------------------------------------- latex_elements = { -# The paper size ('letterpaper' or 'a4paper'). -#'papersize': 'letterpaper', - -# The font size ('10pt', '11pt' or '12pt'). -#'pointsize': '10pt', - -# Additional stuff for the LaTeX preamble. -#'preamble': '', - -# Latex figure (float) alignment -#'figure_align': 'htbp', + # The paper size ('letterpaper' or 'a4paper'). + #'papersize': 'letterpaper', + # The font size ('10pt', '11pt' or '12pt'). + #'pointsize': '10pt', + # Additional stuff for the LaTeX preamble. + #'preamble': '', + # Latex figure (float) alignment + #'figure_align': 'htbp', } # Grouping the document tree into LaTeX files. List of tuples # (source start file, target name, title, # author, documentclass [howto, manual, or own class]). latex_documents = [ - (master_doc, 'FontParts.tex', u'FontParts Documentation', - u'Dr. Rob O. Fab', 'manual'), + ( + master_doc, + "FontParts.tex", + "FontParts Documentation", + "Dr. Rob O. Fab", + "manual", + ), ] # The name of an image file (relative to this directory) to place at the top of # the title page. -#latex_logo = None +# latex_logo = None # For "manual" documents, if this is true, then toplevel headings are parts, # not chapters. -#latex_use_parts = False +# latex_use_parts = False # If true, show page references after internal links. -#latex_show_pagerefs = False +# latex_show_pagerefs = False # If true, show URL addresses after external links. -#latex_show_urls = False +# latex_show_urls = False # Documents to append as an appendix to all manuals. -#latex_appendices = [] +# latex_appendices = [] # If false, no module index is generated. -#latex_domain_indices = True +# latex_domain_indices = True # -- Options for manual page output --------------------------------------- # One entry per manual page. List of tuples # (source start file, name, description, authors, manual section). -man_pages = [ - (master_doc, 'fontparts', u'FontParts Documentation', - [author], 1) -] +man_pages = [(master_doc, "fontparts", "FontParts Documentation", [author], 1)] # If true, show URL addresses after external links. -#man_show_urls = False +# man_show_urls = False # -- Options for Texinfo output ------------------------------------------- @@ -329,22 +327,28 @@ def __getattr__(cls, name): # (source start file, target name, title, author, # dir menu entry, description, category) texinfo_documents = [ - (master_doc, 'FontParts', u'FontParts Documentation', - author, 'FontParts', 'One line description of project.', - 'Miscellaneous'), + ( + master_doc, + "FontParts", + "FontParts Documentation", + author, + "FontParts", + "One line description of project.", + "Miscellaneous", + ), ] # Documents to append as an appendix to all manuals. -#texinfo_appendices = [] +# texinfo_appendices = [] # If false, no module index is generated. -#texinfo_domain_indices = True +# texinfo_domain_indices = True # How to display URL addresses: 'footnote', 'no', or 'inline'. -#texinfo_show_urls = 'footnote' +# texinfo_show_urls = 'footnote' # If true, do not generate a @detailmenu in the "Top" node's menu. -#texinfo_no_detailmenu = False +# texinfo_no_detailmenu = False #################### @@ -358,11 +362,15 @@ def __getattr__(cls, name): from sphinx import addnodes from sphinx.util import rst from docutils.parsers.rst import directives -from sphinx.ext.autosummary import Autosummary, import_by_name, get_import_prefixes_from_env, autosummary_table +from sphinx.ext.autosummary import ( + Autosummary, + import_by_name, + get_import_prefixes_from_env, + autosummary_table, +) class AutosummaryMethodList(Autosummary): - option_spec = dict(Autosummary.option_spec) option_spec["hidesummary"] = directives.flag @@ -377,7 +385,13 @@ def get_items(self, names): for name in names: methodNames.append(name) _, obj, _, _ = import_by_name(name, prefixes=prefixes) - methodNames.extend(["%s.%s" % (name, method) for method in dir(obj) if not method.startswith("_")]) + methodNames.extend( + [ + "%s.%s" % (name, method) + for method in dir(obj) + if not method.startswith("_") + ] + ) return super(AutosummaryMethodList, self).get_items(methodNames) def get_table(self, items): @@ -385,41 +399,46 @@ def get_table(self, items): Subclass to get support for `hidesummary` as options to enable displaying the short summary in the table """ - hidesummary = 'hidesummary' in self.options + hidesummary = "hidesummary" in self.options table_spec = addnodes.tabular_col_spec() - table_spec['spec'] = 'p{0.5\linewidth}p{0.5\linewidth}' + table_spec["spec"] = "p{0.5\linewidth}p{0.5\linewidth}" - table = autosummary_table('') - real_table = nodes.table('', classes=['longtable']) + table = autosummary_table("") + real_table = nodes.table("", classes=["longtable"]) table.append(real_table) - group = nodes.tgroup('', cols=2) + group = nodes.tgroup("", cols=2) real_table.append(group) - group.append(nodes.colspec('', colwidth=10)) - group.append(nodes.colspec('', colwidth=90)) - body = nodes.tbody('') + group.append(nodes.colspec("", colwidth=10)) + group.append(nodes.colspec("", colwidth=90)) + body = nodes.tbody("") group.append(body) def append_row(*column_texts): - row = nodes.row('') + row = nodes.row("") for text in column_texts: - node = nodes.paragraph('') + node = nodes.paragraph("") vl = ViewList() - vl.append(text, '') + vl.append(text, "") self.state.nested_parse(vl, 0, node) try: if isinstance(node[0], nodes.paragraph): node = node[0] except IndexError: pass - row.append(nodes.entry('', node)) + row.append(nodes.entry("", node)) body.append(row) for name, sig, summary, real_name in items: - qualifier = 'obj' - if 'nosignatures' not in self.options: - col1 = ':%s:`%s <%s>`\ %s' % (qualifier, name, real_name, rst.escape(sig)) + qualifier = "obj" + if "nosignatures" not in self.options: + col1 = ":%s:`%s <%s>`\ %s" % ( + qualifier, + name, + real_name, + rst.escape(sig), + ) else: - col1 = ':%s:`%s <%s>`' % (qualifier, name, real_name) + col1 = ":%s:`%s <%s>`" % (qualifier, name, real_name) col2 = summary if hidesummary: append_row(col1) @@ -428,21 +447,31 @@ def append_row(*column_texts): return [table_spec, table] + def setup(app): - app.add_directive('autosummarymethodlist', AutosummaryMethodList) + app.add_directive("autosummarymethodlist", AutosummaryMethodList) from pygments.style import Style -from pygments.token import Keyword, Name, Comment, String, Error, \ - Number, Operator, Generic +from pygments.token import ( + Keyword, + Name, + Comment, + String, + Error, + Number, + Operator, + Generic, +) + class YourStyle(Style): default_style = "" styles = { - Comment: 'italic #888', - Keyword: 'bold #005', - Name: '#f00', - Name.Function: '#0f0', - Name.Class: 'bold #0f0', - String: 'bg:#eee #111' + Comment: "italic #888", + Keyword: "bold #005", + Name: "#f00", + Name.Function: "#0f0", + Name.Class: "bold #0f0", + String: "bg:#eee #111", } diff --git a/documentation/tools/docstring.py b/documentation/tools/docstring.py index 199cb97f..d826a6c8 100644 --- a/documentation/tools/docstring.py +++ b/documentation/tools/docstring.py @@ -61,7 +61,7 @@ Optional, Set, Tuple, - Union + Union, ) from abc import ABC, abstractmethod @@ -78,81 +78,57 @@ GetterSetterType = Tuple[OptionalCallable, OptionalCallable] ParsedAnnotation = Union[str, Tuple[str, List[Any]]] -NORMALIZATION_MODULE = 'normalizers' -DEPRECATION_ID = 'This method is deprecated.' -INDENT = ' ' * 4 +NORMALIZATION_MODULE = "normalizers" +DEPRECATION_ID = "This method is deprecated." +INDENT = " " * 4 LINE_LENGTH = 72 FORMAT_STRINGS: Dict[str, str] = { - 'implementationNote': ( - "This is the environment implementation of {baseObject}." - ), - 'getterImplementationNote': ( + "implementationNote": ("This is the environment implementation of {baseObject}."), + "getterImplementationNote": ( "This is the environment implementation of the {baseObject} property getter." ), - 'setterImplementationNote': ( + "setterImplementationNote": ( "This is the environment implementation of the {baseObject} property setter." ), - 'deprecated': ( - "This method is deprecated. Use {replacement} instead." - ), - 'mayOverride': ( - "Subclasses may override this method." - ), - 'mustOverride': ( - "Subclasses must override this method." - ), - 'parameter': ( - ":param {parameterName}: Description of {typeString}." - ), - 'normalizer': ( - " The value will have been normalized with :func:`{normalizer}`." - ), - 'default': ( - " Defaults to {value}." - ), - 'raises': ( - ":raises {exception}: If {condition}." - ), - 'exception': ( - "description" - ), - 'notImplementedError': ( - "the method has not been overridden by a subclass" - ), - 'return': ( - ":return: {typeString}." - ), - 'setterValue': ( - "The value must be {typeString}." - ), + "deprecated": ("This method is deprecated. Use {replacement} instead."), + "mayOverride": ("Subclasses may override this method."), + "mustOverride": ("Subclasses must override this method."), + "parameter": (":param {parameterName}: Description of {typeString}."), + "normalizer": (" The value will have been normalized with :func:`{normalizer}`."), + "default": (" Defaults to {value}."), + "raises": (":raises {exception}: If {condition}."), + "exception": ("description"), + "notImplementedError": ("the method has not been overridden by a subclass"), + "return": (":return: {typeString}."), + "setterValue": ("The value must be {typeString}."), } ROLE_PREFIXES: Dict[str, str] = { - 'function': ':func:', - 'method': ':meth:', - 'property': ':attr:', - 'attribute': ':attr:', - 'NoneType': ':obj:', - 'None': ':obj:', - 'True': ':obj:', - 'False': ':obj:', - 'list': ':class:', - 'tuple': ':class:', - 'dict': ':class:`', - 'int': ':class:', - 'float': ':class:', - 'str': ':class:', + "function": ":func:", + "method": ":meth:", + "property": ":attr:", + "attribute": ":attr:", + "NoneType": ":obj:", + "None": ":obj:", + "True": ":obj:", + "False": ":obj:", + "list": ":class:", + "tuple": ":class:", + "dict": ":class:`", + "int": ":class:", + "float": ":class:", + "str": ":class:", } DIRECTIVES: Dict[str, str] = { - 'deprecated': '.. deprecated::', - 'note': '.. note::', - 'important': '.. important::', - 'seealso': '.. seealso::', - 'tip': '.. tip::', - 'todo': '.. todo::' + "deprecated": ".. deprecated::", + "note": ".. note::", + "important": ".. important::", + "seealso": ".. seealso::", + "tip": ".. tip::", + "todo": ".. todo::", } @@ -197,15 +173,13 @@ def _mergeTypeHints(self) -> Dict[str, Optional[Any]]: return {} typeHints = {} - getterHints = get_type_hints( - self.getterObject, globalns=self.globalNamespace - ) - typeHints['value'] = getterHints.get('return', None) + getterHints = get_type_hints(self.getterObject, globalns=self.globalNamespace) + typeHints["value"] = getterHints.get("return", None) if self.setterObject: setterHints = get_type_hints( self.setterObject, globalns=self.globalNamespace ) - typeHints['return'] = setterHints.get('value', None) + typeHints["return"] = setterHints.get("value", None) return typeHints def _formatValue(self, value: Any) -> str: @@ -220,24 +194,24 @@ def _formatValue(self, value: Any) -> str: def dynamicPropertyObject(self) -> Optional[dynamicProperty]: """Get the current object's associated dynamicProperty.""" if self.isGetter or self.isSetter: - dynamicPropertyName = self.dynamicPropertyQualname.split('.')[1] + dynamicPropertyName = self.dynamicPropertyQualname.split(".")[1] return getattr(self.containingClass, dynamicPropertyName) return None @property def isGetter(self) -> bool: """Check if the current object is a getter.""" - return '_get_' in self.objectName + return "_get_" in self.objectName @property def isSetter(self) -> bool: """Check if the current object is a setter.""" - return '_set_' in self.objectName + return "_set_" in self.objectName @property def dynamicPropertyQualname(self) -> str: """Get the qualified name of the dynamic property.""" - return re.sub(r'_base|_get_|_set_', '', self.objectName) + return re.sub(r"_base|_get_|_set_", "", self.objectName) @property def getterObject(self) -> OptionalCallable: @@ -309,14 +283,14 @@ def setterValueDescription(self) -> str: """Generate the description string for the setter value.""" signature = self._mergeSignatures() if not signature or not self.setterObject: - return '' + return "" for name in signature.parameters: - if name == 'self': + if name == "self": continue typeString = self._createTypeString(name) - formatString = FORMAT_STRINGS['setterValue'].format( + formatString = FORMAT_STRINGS["setterValue"].format( parameterName=name, typeString=typeString ) @@ -324,14 +298,14 @@ def setterValueDescription(self) -> str: normalizerDict = self._getNormalizers(source) if normalizerDict and name in normalizerDict: normalizer = normalizerDict[name] - formatString += FORMAT_STRINGS['normalizer'].format( + formatString += FORMAT_STRINGS["normalizer"].format( normalizer=normalizer ) - defaults = self._getSignatureInfo().get('defaults') + defaults = self._getSignatureInfo().get("defaults") if defaults and name in defaults: value = self._formatValue(defaults[name]) - formatString += FORMAT_STRINGS['default'].format(value=value) + formatString += FORMAT_STRINGS["default"].format(value=value) wrapped = textwrap.fill(formatString, LINE_LENGTH, subsequent_indent=INDENT) return wrapped @@ -340,21 +314,19 @@ def setterValueDescription(self) -> str: def implementationNote(self) -> str: """Generate an implementation note for the dynamic property.""" if not self.publicQualname: - return '' + return "" role = self._assignRole(self.publicQualname) if self.isGetter: - formatString = FORMAT_STRINGS['getterImplementationNote'].format( + formatString = FORMAT_STRINGS["getterImplementationNote"].format( baseObject=role ) elif self.isSetter: - formatString = FORMAT_STRINGS['setterImplementationNote'].format( + formatString = FORMAT_STRINGS["setterImplementationNote"].format( baseObject=role ) else: - formatString = FORMAT_STRINGS['implementationNote'].format( - baseObject=role - ) + formatString = FORMAT_STRINGS["implementationNote"].format(baseObject=role) return textwrap.fill(formatString, LINE_LENGTH) @@ -377,17 +349,19 @@ class CodeAnalyzer(ast.NodeVisitor): """ - def __init__(self, normalizationModule: str = 'normalizers'): + def __init__(self, normalizationModule: str = "normalizers"): self.exceptions: Set[str] = set() self.normalizers: Dict[str, str] = {} self.normalizationModule = normalizationModule def _extractNormalizer(self, node: ast.Call) -> Optional[str]: """Extract the normalizer function.""" - if (isinstance(node.func, ast.Attribute) + if ( + isinstance(node.func, ast.Attribute) and isinstance(node.func.value, ast.Name) - and node.func.value.id == self.normalizationModule): - return f'{self.normalizationModule}.{node.func.attr}' + and node.func.value.id == self.normalizationModule + ): + return f"{self.normalizationModule}.{node.func.attr}" return None def visit_Raise(self, node: ast.Raise) -> None: @@ -403,9 +377,8 @@ def visit_Raise(self, node: ast.Raise) -> None: def visit_Call(self, node: ast.Call) -> None: """Analyze function calls.""" - if (hasattr(node.func, 'attr') - and node.func.attr == 'raiseNotImplementedError'): - self.exceptions.add('NotImplementedError') + if hasattr(node.func, "attr") and node.func.attr == "raiseNotImplementedError": + self.exceptions.add("NotImplementedError") normalizer = self._extractNormalizer(node) if normalizer and node.args and isinstance(node.args[0], ast.Name): @@ -418,11 +391,11 @@ def visit_Return(self, node: ast.Return) -> None: if isinstance(node.value, ast.Call): normalizer = self._extractNormalizer(node.value) if normalizer and isinstance(node.value.args[0], ast.Name): - self.normalizers['return'] = normalizer + self.normalizers["return"] = normalizer elif isinstance(node.value, ast.Name): returnValue = node.value.id if returnValue in self.normalizers: - self.normalizers['return'] = self.normalizers[returnValue] + self.normalizers["return"] = self.normalizers[returnValue] self.generic_visit(node) @@ -452,14 +425,16 @@ class Docstring(DynamicPropertyMixin): """ - def __init__(self, - obj: Any, - containingClass: Optional[Any] = None, - summary: Optional[str] = None, - description: Optional[str] = None, - examples: Optional[str] = None, - preserveVariadics: bool = True, - globalNamespace: Optional[dict] = None): + def __init__( + self, + obj: Any, + containingClass: Optional[Any] = None, + summary: Optional[str] = None, + description: Optional[str] = None, + examples: Optional[str] = None, + preserveVariadics: bool = True, + globalNamespace: Optional[dict] = None, + ): self._obj = obj self._containingClass = containingClass self._summary = summary @@ -480,9 +455,9 @@ def _getSignatureInfo(self) -> Dict[str, Any]: from collections import defaultdict result: defaultdict[str, Union[dict, ParsedAnnotation]] = defaultdict(dict) - result['annotations'] = self._extractParameterAnnotations() - result['defaults'] = self._extractDefaultValues() - result['return'] = self._extractReturnAnnotation() + result["annotations"] = self._extractParameterAnnotations() + result["defaults"] = self._extractDefaultValues() + result["return"] = self._extractReturnAnnotation() return dict(result) @@ -492,7 +467,7 @@ def _extractParameterAnnotations(self) -> Dict[str, ParsedAnnotation]: hints = self._getTypeHints() signature = self._getSignature() for name, param in signature.parameters.items(): - if name in {'self', 'cls'}: + if name in {"self", "cls"}: continue annotation = hints.get(name, param.annotation) @@ -506,7 +481,7 @@ def _extractReturnAnnotation(self) -> Optional[ParsedAnnotation]: signature = self._getSignature() if signature: - returnAnnotation = hints.get('return', signature.return_annotation) + returnAnnotation = hints.get("return", signature.return_annotation) return self._parseTypeAnnotation(returnAnnotation) return None @@ -515,7 +490,7 @@ def _extractDefaultValues(self) -> Dict[str, Any]: defaults = {} signature = self._getSignature() for name, param in signature.parameters.items(): - if name in {'self', 'cls'}: + if name in {"self", "cls"}: continue if param.default is not inspect.Signature.empty: defaults[name] = param.default @@ -554,33 +529,31 @@ def _createTypeString(self, key: Optional[str] = None) -> str: def _typeToString(annotation: Any) -> str: if isinstance(annotation, tuple): container, elements = annotation[0], annotation[1] - if container == 'typing.Union': + if container == "typing.Union": return " or ".join([_typeToString(e) for e in elements]) return ( f"{self._assignRole(container)} of " f"{', '.join([_typeToString(e) for e in elements])} " f"items" ) - elif annotation.startswith('Optional[') and annotation.endswith(']'): - elements = [annotation[9:-1], 'None'] + elif annotation.startswith("Optional[") and annotation.endswith("]"): + elements = [annotation[9:-1], "None"] return " or ".join([_typeToString(e) for e in elements]) return self._assignRole(annotation) return _typeToString(annotation) - def _parseTypeAnnotation(self, - annotation: Any - ) -> ParsedAnnotation: + def _parseTypeAnnotation(self, annotation: Any) -> ParsedAnnotation: # Parses the type annotation of a parameter or return type. # builtins try: - if hasattr(annotation, '__name__'): + if hasattr(annotation, "__name__"): return annotation.__name__ origin = get_origin(annotation) if origin is not None: - if hasattr(origin, '__name__'): + if hasattr(origin, "__name__"): containerName = origin.__name__ else: containerName = str(origin) @@ -600,67 +573,63 @@ def _parseTypeAnnotation(self, def _getSignature(self) -> Optional[inspect.Signature]: # Select signature getter based on object type. - if (not isinstance(self.obj, type) - and self.objectName == 'dynamicProperty'): + if not isinstance(self.obj, type) and self.objectName == "dynamicProperty": return self._mergeSignatures() return inspect.signature(self.obj) def _getTypeHints(self) -> Dict[str, Any]: # Select type hint getter based on object type. - if self.objectName == 'dynamicProperty': + if self.objectName == "dynamicProperty": return self._mergeTypeHints() return get_type_hints(self.obj, globalns=self.globalNamespace) def _assignRole(self, objectName: str) -> str: # Assign a role to an object based on its type. - if objectName == 'NoneType': - return ':obj:`None`' + if objectName == "NoneType": + return ":obj:`None`" def removePrefix(string: str, prefix: str) -> str: # Remove a specified prefix from a string. if string and string.startswith(prefix): - return string[len(prefix):] + return string[len(prefix) :] return string def getMemberRole(objectName: str) -> str: # Determine the role of a class member (method, function, etc.). - className, memberName = objectName.split('.', 1) + className, memberName = objectName.split(".", 1) obj = self.globalNamespace.get(className) member = getattr(obj, memberName, None) typeName = type(obj).__name__ if callable(member): if isinstance(member, type(lambda: None)): - typeName = 'method' + typeName = "method" else: - typeName = 'function' + typeName = "function" elif isinstance(member, property): - typeName = 'property' + typeName = "property" else: - typeName = 'attribute' - return ROLE_PREFIXES.get(typeName, '') + typeName = "attribute" + return ROLE_PREFIXES.get(typeName, "") - objectName = removePrefix(objectName, 'typing.') + objectName = removePrefix(objectName, "typing.") if self.isQualified(objectName): prefix = getMemberRole(objectName) else: - prefix = ROLE_PREFIXES.get(objectName, '') - return (f'{prefix}`{objectName}`' - if prefix else f':class:`{objectName}`') + prefix = ROLE_PREFIXES.get(objectName, "") + return f"{prefix}`{objectName}`" if prefix else f":class:`{objectName}`" def _resolveSource(self) -> str: # Resolves the source based on object type. if self.dynamicPropertyObject: if self.isGetter: obj = Docstring( - self.dynamicPropertyObject, - containingClass=self.containingClass + self.dynamicPropertyObject, containingClass=self.containingClass ).getterObject elif self.isSetter: obj = Docstring( - self.dynamicPropertyObject, - containingClass=self.containingClass + self.dynamicPropertyObject, containingClass=self.containingClass ).setterObject elif self.isPrivate: obj = self.publicObject @@ -677,7 +646,7 @@ def isQualified(objectName) -> bool: :obj:`False` otherwise. """ - return objectName and '.' in objectName and objectName[0].isupper() + return objectName and "." in objectName and objectName[0].isupper() # ------------------ # Docstring Elements @@ -695,34 +664,34 @@ def summary(self) -> str: """ if self.isPrivate and self.publicQualname: - _, publicName = self.publicQualname.split('.') + _, publicName = self.publicQualname.split(".") try: publicObject = getattr(self.containingClass, publicName) - summary = publicObject.__doc__.split('\n')[0] + summary = publicObject.__doc__.split("\n")[0] except AttributeError: - summary = 'Summary line' + summary = "Summary line" if self.isGetter: - summary = summary.replace('Get or set', 'Get') + summary = summary.replace("Get or set", "Get") elif self.isSetter: - summary = summary.replace('Get or set', 'Set') - return summary or 'Summary line' + summary = summary.replace("Get or set", "Set") + return summary or "Summary line" if self._summary and len(self._summary) > LINE_LENGTH: logging.warning( "The provided 'summary' value is longer than %s characters.", - LINE_LENGTH + LINE_LENGTH, ) - return self._summary or 'Summary line' + return self._summary or "Summary line" @property def deprecationNotice(self) -> str: """Provide a formatted deprecation notice if object is deprecated.""" objectDocstring = inspect.getdoc(self.obj) if not objectDocstring: - return '' + return "" - pattern = re.compile('`(.*)`') + pattern = re.compile("`(.*)`") for line in objectDocstring.splitlines(): if DEPRECATION_ID not in line: @@ -734,12 +703,13 @@ def deprecationNotice(self) -> str: replacementName = replacementMatch.group(1) assignedReplacement = self._assignRole(replacementName) - formatString = FORMAT_STRINGS['deprecated'].format( - replacement=assignedReplacement) + formatString = FORMAT_STRINGS["deprecated"].format( + replacement=assignedReplacement + ) directive = f"{DIRECTIVES['deprecated']}\n\n{INDENT}{formatString}" return directive - return '' + return "" @property def description(self) -> str: @@ -749,31 +719,34 @@ def description(self) -> str: description. """ - description = textwrap.fill(self._description or 'Description', LINE_LENGTH) + description = textwrap.fill(self._description or "Description", LINE_LENGTH) if self.isPrivate: - return "\n\n".join([description, self.implementationNote] - if self.implementationNote else [description]) + return "\n\n".join( + [description, self.implementationNote] + if self.implementationNote + else [description] + ) return description @property def paramSection(self) -> str: """Get the parameter section of the docstring.""" - if not isinstance(self.obj, type) and self.objectName == 'dynamicProperty': + if not isinstance(self.obj, type) and self.objectName == "dynamicProperty": return self.setterValueDescription lines = [] signature = inspect.signature(self.obj) for name, param in signature.parameters.items(): - if name == 'self': + if name == "self": continue typeString = self._createTypeString(name) # Handle variadics. - if str(param).startswith('*') and self.preserveVariadics: + if str(param).startswith("*") and self.preserveVariadics: name = f"\\{str(param)}" - formatString = FORMAT_STRINGS['parameter'].format( + formatString = FORMAT_STRINGS["parameter"].format( parameterName=name, typeString=typeString ) @@ -782,35 +755,35 @@ def paramSection(self) -> str: normalizerDict = self._getNormalizers(source) if normalizerDict and name in normalizerDict: normalizer = normalizerDict[name] - formatString += FORMAT_STRINGS['normalizer'].format( + formatString += FORMAT_STRINGS["normalizer"].format( normalizer=normalizer ) - defaults = self._getSignatureInfo().get('defaults') + defaults = self._getSignatureInfo().get("defaults") if defaults and name in defaults: value = self._formatValue(defaults[name]) - formatString += FORMAT_STRINGS['default'].format(value=value) + formatString += FORMAT_STRINGS["default"].format(value=value) wrapped = textwrap.fill(formatString, LINE_LENGTH, subsequent_indent=INDENT) lines.append(wrapped) - return '\n'.join(lines) or '' + return "\n".join(lines) or "" @property def returnSection(self) -> str: """Get the return section of the docstring.""" returnValue = self._extractReturnAnnotation() - if returnValue in ['NoneType', 'None']: - return '' + if returnValue in ["NoneType", "None"]: + return "" typeString = self._createTypeString() - formatString = FORMAT_STRINGS['return'].format(typeString=typeString) + formatString = FORMAT_STRINGS["return"].format(typeString=typeString) if self.isPrivate: source = self._resolveSource() normalizerDict = self._getNormalizers(source) - if normalizerDict and 'return' in normalizerDict: - normalizer = normalizerDict['return'] - formatString += FORMAT_STRINGS['normalizer'].format( + if normalizerDict and "return" in normalizerDict: + normalizer = normalizerDict["return"] + formatString += FORMAT_STRINGS["normalizer"].format( normalizer=normalizer ) @@ -819,36 +792,32 @@ def returnSection(self) -> str: @property def raisesSection(self) -> str: """Get the raises section of the docstring.""" - if self.objectName == 'dynamicProperty': - return '' + if self.objectName == "dynamicProperty": + return "" exceptions = self._getRaisedExceptions() lines = [] for exc in exceptions: - condition = FORMAT_STRINGS['exception'] - if exc == 'NotImplementedError': - condition = FORMAT_STRINGS['notImplementedError'] - formatString = FORMAT_STRINGS['raises'].format( + condition = FORMAT_STRINGS["exception"] + if exc == "NotImplementedError": + condition = FORMAT_STRINGS["notImplementedError"] + formatString = FORMAT_STRINGS["raises"].format( exception=exc, condition=condition ) wrapped = textwrap.fill(formatString, LINE_LENGTH, subsequent_indent=INDENT) lines.append(wrapped) - return '\n'.join(lines) or '' + return "\n".join(lines) or "" @property def overrideNotice(self) -> str: """Get an override notice based on the override value.""" if self.overrideValue == 0: - return '' - delimiter = '\n\n' + INDENT + return "" + delimiter = "\n\n" + INDENT if self.overrideValue == 1: - return (DIRECTIVES['note'] - + delimiter - + FORMAT_STRINGS['mayOverride']) - return (DIRECTIVES['important'] - + delimiter - + FORMAT_STRINGS['mustOverride']) + return DIRECTIVES["note"] + delimiter + FORMAT_STRINGS["mayOverride"] + return DIRECTIVES["important"] + delimiter + FORMAT_STRINGS["mustOverride"] @property def examples(self) -> str: @@ -856,13 +825,13 @@ def examples(self) -> str: found = [] docstring = inspect.getdoc(self.obj) if not docstring: - return '' + return "" - for element in docstring.split('\n\n'): - if element.strip().startswith('>>>'): + for element in docstring.split("\n\n"): + if element.strip().startswith(">>>"): found.append(element) - delimiter = '\n\n' - return f"Example::{delimiter}{delimiter.join(found)}" if found else '' + delimiter = "\n\n" + return f"Example::{delimiter}{delimiter.join(found)}" if found else "" # ---------------- # Other properties @@ -882,7 +851,7 @@ def containingClass(self) -> Optional[Any]: def publicObject(self): """Get the public equivalen of the object.""" try: - return getattr(self.containingClass, self.publicQualname.split('.')[-1]) + return getattr(self.containingClass, self.publicQualname.split(".")[-1]) except AttributeError: return self.obj @@ -912,8 +881,8 @@ def isPrivate(self) -> bool: """Check if the object is private (starts with an underscore).""" objectName = self.objectName if self.isQualified(objectName): - _, objectName = objectName.split('.') - return objectName.startswith('_') + _, objectName = objectName.split(".") + return objectName.startswith("_") @property def isBase(self) -> bool: @@ -931,15 +900,16 @@ def publicQualname(self) -> str: exists in the containing class and returns the formatted name. """ + def getNamespace(objectName: str) -> str: # Get the name of the object's namespace (i.e., the part of the # qualname before the last dot) from `objectName` or `containingClass`. - if '.' in objectName: - segments = objectName.split('.') - return '.'.join(segments[:-1]) + if "." in objectName: + segments = objectName.split(".") + return ".".join(segments[:-1]) if self.containingClass: return self.containingClass.__class__.__qualname__ - return '' + return "" def objectExists(publicMemberName: str) -> bool: # Check if an object exists within a class. @@ -947,19 +917,22 @@ def objectExists(publicMemberName: str) -> bool: self.containingClass, publicMemberName ) - if self.dynamicPropertyObject.__class__.__name__ == 'dynamicProperty': + if self.dynamicPropertyObject.__class__.__name__ == "dynamicProperty": return self.dynamicPropertyQualname namespace = getNamespace(self.objectName) - memberName = (self.objectName.split('.')[-1] - if '.' in self.objectName else self.objectName) + memberName = ( + self.objectName.split(".")[-1] + if "." in self.objectName + else self.objectName + ) publicMemberName = memberName[1:] if self.isPrivate else memberName if not objectExists(publicMemberName): magicMemberName = f"__{publicMemberName.lower()}__" if not objectExists(magicMemberName): raise ValueError(f"Cannot find public member for '{memberName}'.") publicMemberName = magicMemberName - return '.'.join([namespace, publicMemberName]) + return ".".join([namespace, publicMemberName]) @property def overrideValue(self) -> int: @@ -978,9 +951,7 @@ def overrideValue(self) -> int: return 0 -def insertDocstring(obj: Any, - newDocstring: str, - preserveVariadics: bool = True) -> str: +def insertDocstring(obj: Any, newDocstring: str, preserveVariadics: bool = True) -> str: """Insert the generated docstring into the source code of the object. :param obj: The object whose docstring will be modified. @@ -994,20 +965,18 @@ def insertDocstring(obj: Any, source = inspect.getsource(obj) sourceLines = source.splitlines() match = re.match(r"(\s*)", sourceLines[0]) - indent = match.group(1) if match else '' + indent = match.group(1) if match else "" # Format the docstring with correct indentation. formattedDocstring = textwrap.indent(newDocstring.strip(), indent * 2) # Remove the leading triple quotes and ensure # the correct placement of closing triple quotes. - formattedDocstring = ( - f'"""{formattedDocstring[3:].strip()}\n\n{indent * 2}"""' - ) + formattedDocstring = f'"""{formattedDocstring[3:].strip()}\n\n{indent * 2}"""' # Handle variadics. - if '\\*' in formattedDocstring and preserveVariadics: - formattedDocstring = f'r{formattedDocstring}' + if "\\*" in formattedDocstring and preserveVariadics: + formattedDocstring = f"r{formattedDocstring}" # Replace existing docstring or insert a new one, if obj.__doc__: @@ -1016,28 +985,31 @@ def insertDocstring(obj: Any, ) else: signatureEnd = next( - i for i, line in enumerate(sourceLines) - if line.strip().endswith(':') + i for i, line in enumerate(sourceLines) if line.strip().endswith(":") ) updatedSourceCode = ( - '\n'.join(sourceLines[:signatureEnd + 1]) - + f'\n{indent}{formattedDocstring}\n' - + '\n'.join(sourceLines[signatureEnd + 1:]) + "\n".join(sourceLines[: signatureEnd + 1]) + + f"\n{indent}{formattedDocstring}\n" + + "\n".join(sourceLines[signatureEnd + 1 :]) ) return updatedSourceCode except TypeError as exc: - raise TypeError(f"The source of a {obj.__class__.__name__} " - "instance can not be inspected.") from exc - - -def generateDocstring(obj: Any, - summary: Optional[str] = None, - description: Optional[str] = None, - examples: Optional[str] = None, - preserveVariadics: bool = True, - globalNamespace: Optional[dict] = None, - containingClass: Optional[Any] = None) -> str: + raise TypeError( + f"The source of a {obj.__class__.__name__} " + "instance can not be inspected." + ) from exc + + +def generateDocstring( + obj: Any, + summary: Optional[str] = None, + description: Optional[str] = None, + examples: Optional[str] = None, + preserveVariadics: bool = True, + globalNamespace: Optional[dict] = None, + containingClass: Optional[Any] = None, +) -> str: """Generate a docstring for the object. Creates a docstring with sections including summary, description, @@ -1062,7 +1034,7 @@ def generateDocstring(obj: Any, description=description, examples=examples, preserveVariadics=preserveVariadics, - globalNamespace=globalNamespace + globalNamespace=globalNamespace, ) preliminarySections = [ @@ -1077,12 +1049,9 @@ def generateDocstring(obj: Any, docstring.raisesSection, ] - conclusiveSections = [ - docstring.overrideNotice, - docstring.examples - ] + conclusiveSections = [docstring.overrideNotice, docstring.examples] - preliminaryContent = '\n\n'.join(filter(None, preliminarySections)) - middleContent = '\n'.join(filter(None, middleSections)) - conclusiveContent = '\n\n'.join(filter(None, conclusiveSections)) + preliminaryContent = "\n\n".join(filter(None, preliminarySections)) + middleContent = "\n".join(filter(None, middleSections)) + conclusiveContent = "\n\n".join(filter(None, conclusiveSections)) return f"{preliminaryContent}\n\n{middleContent}\n\n{conclusiveContent}" diff --git a/pyproject.toml b/pyproject.toml index 88dc98a3..abb4cb93 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -3,4 +3,11 @@ requires = ["setuptools>=42", "wheel", "setuptools_scm[toml]>=3.4"] [tool.setuptools_scm] write_to = 'Lib/fontParts/_version.py' -write_to_template = '__version__ = "{version}"' \ No newline at end of file +write_to_template = '__version__ = "{version}"' + +[tool.ruff] +target-version = "py38" + +[tool.ruff.format] +# Enable reformatting of code snippets in docstrings. +docstring-code-format = true diff --git a/setup.py b/setup.py index 564a8859..e557733a 100755 --- a/setup.py +++ b/setup.py @@ -1,29 +1,31 @@ #! /usr/bin/env python from setuptools import setup, find_packages -with open('README.rst', 'r') as f: +with open("README.rst", "r") as f: long_description = f.read() setup_params = dict( - name='fontParts', - description=("An API for interacting with the parts of fonts " - "during the font development process."), - author='Just van Rossum, Tal Leming, Erik van Blokland, Ben Kiel, others', - author_email='info@robofab.com', + name="fontParts", + description=( + "An API for interacting with the parts of fonts " + "during the font development process." + ), + author="Just van Rossum, Tal Leming, Erik van Blokland, Ben Kiel, others", + author_email="info@robofab.com", maintainer="Just van Rossum, Tal Leming, Erik van Blokland, Ben Kiel", maintainer_email="info@robofab.com", - url='http://github.com/robotools/fontParts', + url="http://github.com/robotools/fontParts", license="OpenSource, MIT", platforms=["Any"], long_description=long_description, - package_dir={'': 'Lib'}, - packages=find_packages('Lib'), + package_dir={"": "Lib"}, + packages=find_packages("Lib"), include_package_data=True, use_scm_version={ - "write_to": 'Lib/fontParts/_version.py', - "write_to_template": '__version__ = "{version}"', + "write_to": "Lib/fontParts/_version.py", + "write_to_template": '__version__ = "{version}"', }, - setup_requires=['setuptools_scm'], + setup_requires=["setuptools_scm"], install_requires=[ "FontTools[ufo,lxml,unicode]>=3.32.0", "fontMath>=0.4.8", @@ -44,7 +46,7 @@ "Topic :: Multimedia :: Graphics :: Graphics Conversion", "Topic :: Software Development :: Libraries", ], - python_requires='>=3.8', + python_requires=">=3.8", zip_safe=True, )