simplify ranges() generator

This commit is contained in:
Cosimo Lupo 2021-11-16 12:59:05 +00:00
parent 66ec30c073
commit 07455790b1
2 changed files with 31 additions and 10 deletions

View File

@ -2,7 +2,7 @@ from __future__ import annotations
import re
from functools import lru_cache
from itertools import chain, count, groupby
from itertools import chain, count
from typing import Dict, Iterable, Iterator, List, Optional, Set, Tuple
try:
@ -172,14 +172,19 @@ def update_glyph_href_links(svg: etree.Element, id_map: Dict[str, str]) -> None:
def ranges(ints: Iterable[int]) -> Iterator[Tuple[int, int]]:
# Yield (min, max) ranges of consecutive integers from the input set
sorted_ints = sorted(set(ints))
# to group together consecutive ints, we use as 'key' the difference
# between their index in the (sorted) list and themselves, which stays
# the same for consecutive numbers
for _key, group in groupby(enumerate(sorted_ints), lambda i: i[0] - i[1]):
consecutive_ints = [v for _i, v in group]
yield (consecutive_ints[0], consecutive_ints[-1])
# Yield sorted, non-overlapping (min, max) ranges of consecutive integers
sorted_ints = iter(sorted(set(ints)))
try:
start = end = next(sorted_ints)
except StopIteration:
return
for v in sorted_ints:
if v - 1 == end:
end = v
else:
yield (start, end)
start = end = v
yield (start, end)
@_add_method(ttLib.getTableClass("SVG "))

View File

@ -6,7 +6,7 @@ from fontTools import subset
from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.ttLib import TTFont, newTable
from fontTools.subset.svg import NAMESPACES
from fontTools.subset.svg import NAMESPACES, ranges
import pytest
@ -453,3 +453,19 @@ def test_subset_svg_missing_glyph(empty_svg_font, tmp_path):
subset.main([str(svg_font_path), f"--output-file={subset_path}", f"--gids=2"])
assert "SVG " not in TTFont(subset_path)
@pytest.mark.parametrize(
"ints, expected_ranges",
[
((), []),
((0,), [(0, 0)]),
((0, 1), [(0, 1)]),
((1, 1, 1, 1), [(1, 1)]),
((1, 3), [(1, 1), (3, 3)]),
((4, 2, 1, 3), [(1, 4)]),
((1, 2, 4, 5, 6, 9, 13, 14, 15), [(1, 2), (4, 6), (9, 9), (13, 15)]),
],
)
def test_ranges(ints, expected_ranges):
assert list(ranges(ints)) == expected_ranges