From f6e2e5f78606741b7ab824e9161fa96f2ab93f94 Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 16 Dec 2023 10:36:00 +0100 Subject: [PATCH 1/2] add more test cases for invalid input; add some type annotations --- test-py/test_clipboard.py | 16 ++++++++-------- 1 file changed, 8 insertions(+), 8 deletions(-) diff --git a/test-py/test_clipboard.py b/test-py/test_clipboard.py index 5fc45720e..64affd024 100644 --- a/test-py/test_clipboard.py +++ b/test-py/test_clipboard.py @@ -9,6 +9,8 @@ "inputData, expectedResult", [ ("dasasdad", None), # unparsable + ("' @@ -68,10 +70,8 @@ ), ], ) -def test_parseClipboard(inputData, expectedResult): - result = parseClipboard(inputData) - if result is not None: - result = result +def test_parseClipboard(inputData: str, expectedResult: StaticGlyph): + result: StaticGlyph | None = parseClipboard(inputData) assert expectedResult == result @@ -113,8 +113,8 @@ def test_parseClipboard(inputData, expectedResult): ), ], ) -def test_serializeStaticGlyphAsGLIF(glyphName, glyph, unicodes, expectedResult): - result = serializeStaticGlyphAsGLIF(glyphName, glyph, unicodes) - if result is not None: - result = result +def test_serializeStaticGlyphAsGLIF( + glyphName: str, glyph: StaticGlyph, unicodes: list[int], expectedResult: str +): + result: str = serializeStaticGlyphAsGLIF(glyphName, glyph, unicodes) assert expectedResult == result From e5766b91530bb165d406965e049aef58da5f54bb Mon Sep 17 00:00:00 2001 From: Just van Rossum Date: Sat, 16 Dec 2023 10:37:26 +0100 Subject: [PATCH 2/2] Add type annotations, and handle invalid input better --- src/fontra/core/clipboard.py | 34 +++++++++++++++++++++++----------- 1 file changed, 23 insertions(+), 11 deletions(-) diff --git a/src/fontra/core/clipboard.py b/src/fontra/core/clipboard.py index 51a1e0c3b..44e6c2cc4 100644 --- a/src/fontra/core/clipboard.py +++ b/src/fontra/core/clipboard.py @@ -1,8 +1,11 @@ +from xml.etree.ElementTree import ParseError + from fontTools.pens.boundsPen import ControlBoundsPen from fontTools.pens.pointPen import GuessSmoothPointPen, SegmentToPointPen from fontTools.pens.recordingPen import RecordingPen from fontTools.pens.transformPen import TransformPointPen from fontTools.svgLib import SVGPath +from fontTools.ufoLib.errors import GlifLibError from fontTools.ufoLib.glifLib import readGlyphFromString, writeGlyphToString from ..backends.designspace import UFOGlyph, populateUFOLayerGlyph, readGlyphOrCreate @@ -10,7 +13,7 @@ from .path import PackedPathPointPen -def parseClipboard(data): +def parseClipboard(data: str) -> StaticGlyph | None: if " StaticGlyph | None: + try: + svgPath = SVGPath.fromstring( + data.encode("utf-8"), transform=(1, 0, 0, -1, 0, 0) + ) + except ParseError: + return None recPen = RecordingPen() svgPath.draw(recPen) boundsPen = ControlBoundsPen(None) @@ -36,20 +43,25 @@ def parseSVG(data): return StaticGlyph(path=pen.getPath(), xAdvance=xMax) -def parseGLIF(data): +def parseGLIF(data: str) -> StaticGlyph | None: pen = PackedPathPointPen() ufoGlyph = UFOGlyph() - readGlyphFromString( - data, - glyphObject=ufoGlyph, - pointPen=pen, - ) + try: + readGlyphFromString( + data, + glyphObject=ufoGlyph, + pointPen=pen, + ) + except GlifLibError: + return None return StaticGlyph( path=pen.getPath(), components=pen.components, xAdvance=ufoGlyph.width ) -def serializeStaticGlyphAsGLIF(glyphName, staticGlyph, unicodes): +def serializeStaticGlyphAsGLIF( + glyphName: str, staticGlyph: StaticGlyph, unicodes: list[int] +) -> str: layerGlyph = readGlyphOrCreate({}, glyphName, unicodes) drawPointsFunc = populateUFOLayerGlyph(layerGlyph, staticGlyph) return writeGlyphToString(glyphName, layerGlyph, drawPointsFunc, validate=False)