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

View File

@ -6,7 +6,7 @@ from fontTools import subset
from fontTools.fontBuilder import FontBuilder from fontTools.fontBuilder import FontBuilder
from fontTools.pens.ttGlyphPen import TTGlyphPen from fontTools.pens.ttGlyphPen import TTGlyphPen
from fontTools.ttLib import TTFont, newTable from fontTools.ttLib import TTFont, newTable
from fontTools.subset.svg import NAMESPACES from fontTools.subset.svg import NAMESPACES, ranges
import pytest 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"]) subset.main([str(svg_font_path), f"--output-file={subset_path}", f"--gids=2"])
assert "SVG " not in TTFont(subset_path) 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