Turn AbstractPen and AbstractPointPen into ABCs plus typing
This commit is contained in:
parent
a3acb1426b
commit
ab1883da1d
@ -36,25 +36,52 @@ Coordinates are usually expressed as (x, y) tuples, but generally any
|
||||
sequence of length 2 will do.
|
||||
"""
|
||||
|
||||
import abc
|
||||
from typing import Any, Tuple
|
||||
|
||||
from fontTools.misc.loggingTools import LogMixin
|
||||
|
||||
__all__ = ["AbstractPen", "NullPen", "BasePen",
|
||||
"decomposeSuperBezierSegment", "decomposeQuadraticSegment"]
|
||||
|
||||
|
||||
class AbstractPen(object):
|
||||
class AbstractPen(abc.ABC):
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass: Any) -> bool:
|
||||
if cls is not AbstractPen:
|
||||
return NotImplemented
|
||||
return (
|
||||
hasattr(subclass, "moveTo")
|
||||
and callable(subclass.moveTo)
|
||||
and hasattr(subclass, "lineTo")
|
||||
and callable(subclass.lineTo)
|
||||
and hasattr(subclass, "curveTo")
|
||||
and callable(subclass.curveTo)
|
||||
and hasattr(subclass, "qCurveTo")
|
||||
and callable(subclass.qCurveTo)
|
||||
and hasattr(subclass, "closePath")
|
||||
and callable(subclass.closePath)
|
||||
and hasattr(subclass, "endPath")
|
||||
and callable(subclass.endPath)
|
||||
and hasattr(subclass, "addComponent")
|
||||
and callable(subclass.addComponent)
|
||||
or NotImplemented
|
||||
)
|
||||
|
||||
def moveTo(self, pt):
|
||||
@abc.abstractmethod
|
||||
def moveTo(self, pt: Tuple[float, float]) -> None:
|
||||
"""Begin a new sub path, set the current point to 'pt'. You must
|
||||
end each sub path with a call to pen.closePath() or pen.endPath().
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def lineTo(self, pt):
|
||||
@abc.abstractmethod
|
||||
def lineTo(self, pt: Tuple[float, float]) -> None:
|
||||
"""Draw a straight line from the current point to 'pt'."""
|
||||
raise NotImplementedError
|
||||
|
||||
def curveTo(self, *points):
|
||||
@abc.abstractmethod
|
||||
def curveTo(self, *points: Tuple[float, float]) -> None:
|
||||
"""Draw a cubic bezier with an arbitrary number of control points.
|
||||
|
||||
The last point specified is on-curve, all others are off-curve
|
||||
@ -75,7 +102,8 @@ class AbstractPen(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def qCurveTo(self, *points):
|
||||
@abc.abstractmethod
|
||||
def qCurveTo(self, *points: Tuple[float, float]) -> None:
|
||||
"""Draw a whole string of quadratic curve segments.
|
||||
|
||||
The last point specified is on-curve, all others are off-curve
|
||||
@ -92,19 +120,26 @@ class AbstractPen(object):
|
||||
"""
|
||||
raise NotImplementedError
|
||||
|
||||
def closePath(self):
|
||||
@abc.abstractmethod
|
||||
def closePath(self) -> None:
|
||||
"""Close the current sub path. You must call either pen.closePath()
|
||||
or pen.endPath() after each sub path.
|
||||
"""
|
||||
pass
|
||||
|
||||
def endPath(self):
|
||||
@abc.abstractmethod
|
||||
def endPath(self) -> None:
|
||||
"""End the current sub path, but don't close it. You must call
|
||||
either pen.closePath() or pen.endPath() after each sub path.
|
||||
"""
|
||||
pass
|
||||
|
||||
def addComponent(self, glyphName, transformation):
|
||||
@abc.abstractmethod
|
||||
def addComponent(
|
||||
self,
|
||||
glyphName: str,
|
||||
transformation: Tuple[float, float, float, float, float, float]
|
||||
) -> None:
|
||||
"""Add a sub glyph. The 'transformation' argument must be a 6-tuple
|
||||
containing an affine transformation, or a Transform object from the
|
||||
fontTools.misc.transform module. More precisely: it should be a
|
||||
|
@ -11,8 +11,12 @@ steps through all the points in a call from glyph.drawPoints().
|
||||
This allows the caller to provide more data for each point.
|
||||
For instance, whether or not a point is smooth, and its name.
|
||||
"""
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
|
||||
import abc
|
||||
import math
|
||||
from typing import Any, List, Optional, Tuple
|
||||
|
||||
from fontTools.pens.basePen import AbstractPen
|
||||
|
||||
__all__ = [
|
||||
"AbstractPointPen",
|
||||
@ -24,26 +28,56 @@ __all__ = [
|
||||
]
|
||||
|
||||
|
||||
class AbstractPointPen(object):
|
||||
"""
|
||||
Baseclass for all PointPens.
|
||||
"""
|
||||
class AbstractPointPen(abc.ABC):
|
||||
"""Baseclass for all PointPens."""
|
||||
|
||||
def beginPath(self, identifier=None, **kwargs):
|
||||
@classmethod
|
||||
def __subclasshook__(cls, subclass: Any) -> bool:
|
||||
if cls is not AbstractPointPen:
|
||||
return NotImplemented
|
||||
return (
|
||||
hasattr(subclass, "beginPath")
|
||||
and callable(subclass.beginPath)
|
||||
and hasattr(subclass, "endPath")
|
||||
and callable(subclass.endPath)
|
||||
and hasattr(subclass, "addPoint")
|
||||
and callable(subclass.addPoint)
|
||||
and hasattr(subclass, "addComponent")
|
||||
and callable(subclass.addComponent)
|
||||
or NotImplemented
|
||||
)
|
||||
|
||||
@abc.abstractmethod
|
||||
def beginPath(self, identifier: Optional[str] = None, **kwargs: Any) -> None:
|
||||
"""Start a new sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def endPath(self):
|
||||
@abc.abstractmethod
|
||||
def endPath(self) -> None:
|
||||
"""End the current sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def addPoint(self, pt, segmentType=None, smooth=False, name=None,
|
||||
identifier=None, **kwargs):
|
||||
@abc.abstractmethod
|
||||
def addPoint(
|
||||
self,
|
||||
pt: Tuple[float, float],
|
||||
segmentType: Optional[str] = None,
|
||||
smooth: bool = False,
|
||||
name: Optional[str] = None,
|
||||
identifier: Optional[str] = None,
|
||||
**kwargs: Any
|
||||
) -> None:
|
||||
"""Add a point to the current sub path."""
|
||||
raise NotImplementedError
|
||||
|
||||
def addComponent(self, baseGlyphName, transformation, identifier=None,
|
||||
**kwargs):
|
||||
@abc.abstractmethod
|
||||
def addComponent(
|
||||
self,
|
||||
baseGlyphName: str,
|
||||
transformation: Tuple[float, float, float, float, float, float],
|
||||
identifier: Optional[str] = None,
|
||||
**kwargs: Any
|
||||
) -> None:
|
||||
"""Add a sub glyph."""
|
||||
raise NotImplementedError
|
||||
|
||||
|
@ -1,10 +1,34 @@
|
||||
from fontTools.misc.py23 import *
|
||||
from fontTools.pens.basePen import \
|
||||
BasePen, decomposeSuperBezierSegment, decomposeQuadraticSegment
|
||||
AbstractPen, BasePen, decomposeSuperBezierSegment, decomposeQuadraticSegment
|
||||
from fontTools.pens.pointPen import AbstractPointPen
|
||||
from fontTools.misc.loggingTools import CapturingLogHandler
|
||||
import unittest
|
||||
|
||||
|
||||
def test_subclasshook():
|
||||
class NullPen:
|
||||
def moveTo(self, pt):
|
||||
pass
|
||||
def lineTo(self, pt):
|
||||
pass
|
||||
def curveTo(self, *points):
|
||||
pass
|
||||
def qCurveTo(self, *points):
|
||||
pass
|
||||
def closePath(self):
|
||||
pass
|
||||
def endPath(self):
|
||||
pass
|
||||
def addComponent(self, glyphName, transformation):
|
||||
pass
|
||||
|
||||
assert issubclass(NullPen, AbstractPen)
|
||||
assert isinstance(NullPen(), AbstractPen)
|
||||
assert not issubclass(NullPen, AbstractPointPen)
|
||||
assert not isinstance(NullPen(), AbstractPointPen)
|
||||
|
||||
|
||||
class _TestPen(BasePen):
|
||||
def __init__(self):
|
||||
BasePen.__init__(self, glyphSet={})
|
||||
|
@ -7,6 +7,23 @@ from fontTools.pens.pointPen import AbstractPointPen, PointToSegmentPen, \
|
||||
SegmentToPointPen, GuessSmoothPointPen, ReverseContourPointPen
|
||||
|
||||
|
||||
def test_subclasshook():
|
||||
class NullPen:
|
||||
def beginPath(self, identifier, **kwargs) -> None:
|
||||
pass
|
||||
def endPath(self) -> None:
|
||||
pass
|
||||
def addPoint(self, pt, segmentType, smooth, name, identifier, **kwargs) -> None:
|
||||
pass
|
||||
def addComponent(self, baseGlyphName, transformation, identifier, **kwargs) -> None:
|
||||
pass
|
||||
|
||||
assert issubclass(NullPen, AbstractPointPen)
|
||||
assert isinstance(NullPen(), AbstractPointPen)
|
||||
assert not issubclass(NullPen, AbstractPen)
|
||||
assert not isinstance(NullPen(), AbstractPen)
|
||||
|
||||
|
||||
class _TestSegmentPen(AbstractPen):
|
||||
|
||||
def __init__(self):
|
||||
|
Loading…
x
Reference in New Issue
Block a user