omlish 0.0.0.dev164__py3-none-any.whl → 0.0.0.dev166__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- omlish/.manifests.json +30 -2
 - omlish/__about__.py +2 -2
 - omlish/codecs/__init__.py +3 -0
 - omlish/codecs/base.py +4 -0
 - omlish/codecs/funcs.py +11 -0
 - omlish/codecs/text.py +2 -2
 - omlish/formats/cloudpickle.py +31 -0
 - omlish/formats/json/codecs.py +0 -4
 - omlish/formats/json/delimted.py +4 -0
 - omlish/formats/yaml.py +7 -0
 - omlish/funcs/pairs.py +0 -281
 - omlish/io/compress/codecs.py +20 -0
 - omlish/io/generators/__init__.py +3 -0
 - omlish/io/generators/stepped.py +19 -3
 - omlish/iterators/__init__.py +24 -0
 - omlish/iterators/iterators.py +132 -0
 - omlish/iterators/recipes.py +18 -0
 - omlish/iterators/tools.py +96 -0
 - omlish/iterators/unique.py +67 -0
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/METADATA +1 -1
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/RECORD +25 -19
 - omlish/iterators.py +0 -300
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/LICENSE +0 -0
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/WHEEL +0 -0
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/entry_points.txt +0 -0
 - {omlish-0.0.0.dev164.dist-info → omlish-0.0.0.dev166.dist-info}/top_level.txt +0 -0
 
    
        omlish/iterators.py
    DELETED
    
    | 
         @@ -1,300 +0,0 @@ 
     | 
|
| 
       1 
     | 
    
         
            -
            import collections
         
     | 
| 
       2 
     | 
    
         
            -
            import dataclasses as dc
         
     | 
| 
       3 
     | 
    
         
            -
            import functools
         
     | 
| 
       4 
     | 
    
         
            -
            import heapq
         
     | 
| 
       5 
     | 
    
         
            -
            import itertools
         
     | 
| 
       6 
     | 
    
         
            -
            import typing as ta
         
     | 
| 
       7 
     | 
    
         
            -
             
     | 
| 
       8 
     | 
    
         
            -
            # from . import check
         
     | 
| 
       9 
     | 
    
         
            -
            from . import lang
         
     | 
| 
       10 
     | 
    
         
            -
             
     | 
| 
       11 
     | 
    
         
            -
             
     | 
| 
       12 
     | 
    
         
            -
            T = ta.TypeVar('T')
         
     | 
| 
       13 
     | 
    
         
            -
            U = ta.TypeVar('U')
         
     | 
| 
       14 
     | 
    
         
            -
             
     | 
| 
       15 
     | 
    
         
            -
            _MISSING = object()
         
     | 
| 
       16 
     | 
    
         
            -
             
     | 
| 
       17 
     | 
    
         
            -
             
     | 
| 
       18 
     | 
    
         
            -
            class PeekIterator(ta.Iterator[T]):
         
     | 
| 
       19 
     | 
    
         
            -
             
     | 
| 
       20 
     | 
    
         
            -
                def __init__(self, it: ta.Iterable[T]) -> None:
         
     | 
| 
       21 
     | 
    
         
            -
                    super().__init__()
         
     | 
| 
       22 
     | 
    
         
            -
             
     | 
| 
       23 
     | 
    
         
            -
                    self._it = iter(it)
         
     | 
| 
       24 
     | 
    
         
            -
                    self._pos = -1
         
     | 
| 
       25 
     | 
    
         
            -
                    self._next_item: ta.Any = _MISSING
         
     | 
| 
       26 
     | 
    
         
            -
             
     | 
| 
       27 
     | 
    
         
            -
                _item: T
         
     | 
| 
       28 
     | 
    
         
            -
             
     | 
| 
       29 
     | 
    
         
            -
                def __iter__(self) -> ta.Self:
         
     | 
| 
       30 
     | 
    
         
            -
                    return self
         
     | 
| 
       31 
     | 
    
         
            -
             
     | 
| 
       32 
     | 
    
         
            -
                @property
         
     | 
| 
       33 
     | 
    
         
            -
                def done(self) -> bool:
         
     | 
| 
       34 
     | 
    
         
            -
                    try:
         
     | 
| 
       35 
     | 
    
         
            -
                        self.peek()
         
     | 
| 
       36 
     | 
    
         
            -
                    except StopIteration:
         
     | 
| 
       37 
     | 
    
         
            -
                        return True
         
     | 
| 
       38 
     | 
    
         
            -
                    else:
         
     | 
| 
       39 
     | 
    
         
            -
                        return False
         
     | 
| 
       40 
     | 
    
         
            -
             
     | 
| 
       41 
     | 
    
         
            -
                def __next__(self) -> T:
         
     | 
| 
       42 
     | 
    
         
            -
                    if self._next_item is not _MISSING:
         
     | 
| 
       43 
     | 
    
         
            -
                        self._item = ta.cast(T, self._next_item)
         
     | 
| 
       44 
     | 
    
         
            -
                        self._next_item = _MISSING
         
     | 
| 
       45 
     | 
    
         
            -
                    else:
         
     | 
| 
       46 
     | 
    
         
            -
                        self._item = next(self._it)
         
     | 
| 
       47 
     | 
    
         
            -
                    self._pos += 1
         
     | 
| 
       48 
     | 
    
         
            -
                    return self._item
         
     | 
| 
       49 
     | 
    
         
            -
             
     | 
| 
       50 
     | 
    
         
            -
                def peek(self) -> T:
         
     | 
| 
       51 
     | 
    
         
            -
                    if self._next_item is not _MISSING:
         
     | 
| 
       52 
     | 
    
         
            -
                        return ta.cast(T, self._next_item)
         
     | 
| 
       53 
     | 
    
         
            -
                    self._next_item = next(self._it)
         
     | 
| 
       54 
     | 
    
         
            -
                    return self._next_item
         
     | 
| 
       55 
     | 
    
         
            -
             
     | 
| 
       56 
     | 
    
         
            -
                def next_peek(self) -> T:
         
     | 
| 
       57 
     | 
    
         
            -
                    next(self)
         
     | 
| 
       58 
     | 
    
         
            -
                    return self.peek()
         
     | 
| 
       59 
     | 
    
         
            -
             
     | 
| 
       60 
     | 
    
         
            -
                def takewhile(self, fn: ta.Callable[[T], bool]) -> ta.Iterator[T]:
         
     | 
| 
       61 
     | 
    
         
            -
                    while fn(self.peek()):
         
     | 
| 
       62 
     | 
    
         
            -
                        yield next(self)
         
     | 
| 
       63 
     | 
    
         
            -
             
     | 
| 
       64 
     | 
    
         
            -
                def skipwhile(self, fn: ta.Callable[[T], bool]) -> None:
         
     | 
| 
       65 
     | 
    
         
            -
                    while fn(self.peek()):
         
     | 
| 
       66 
     | 
    
         
            -
                        next(self)
         
     | 
| 
       67 
     | 
    
         
            -
             
     | 
| 
       68 
     | 
    
         
            -
                def takeuntil(self, fn: ta.Callable[[T], bool]) -> ta.Iterator[T]:
         
     | 
| 
       69 
     | 
    
         
            -
                    return self.takewhile(lambda e: not fn(e))
         
     | 
| 
       70 
     | 
    
         
            -
             
     | 
| 
       71 
     | 
    
         
            -
                def skipuntil(self, fn: ta.Callable[[T], bool]) -> None:
         
     | 
| 
       72 
     | 
    
         
            -
                    self.skipwhile(lambda e: not fn(e))
         
     | 
| 
       73 
     | 
    
         
            -
             
     | 
| 
       74 
     | 
    
         
            -
                def takethrough(self, pos: int) -> ta.Iterator[T]:
         
     | 
| 
       75 
     | 
    
         
            -
                    return self.takewhile(lambda _: self._pos < pos)
         
     | 
| 
       76 
     | 
    
         
            -
             
     | 
| 
       77 
     | 
    
         
            -
                def skipthrough(self, pos: int) -> None:
         
     | 
| 
       78 
     | 
    
         
            -
                    self.skipwhile(lambda _: self._pos < pos)
         
     | 
| 
       79 
     | 
    
         
            -
             
     | 
| 
       80 
     | 
    
         
            -
                def taketo(self, pos: int) -> ta.Iterator[T]:
         
     | 
| 
       81 
     | 
    
         
            -
                    return self.takethrough(pos - 1)
         
     | 
| 
       82 
     | 
    
         
            -
             
     | 
| 
       83 
     | 
    
         
            -
                def skipto(self, pos: int) -> None:
         
     | 
| 
       84 
     | 
    
         
            -
                    self.skipthrough(pos - 1)
         
     | 
| 
       85 
     | 
    
         
            -
             
     | 
| 
       86 
     | 
    
         
            -
             
     | 
| 
       87 
     | 
    
         
            -
            class ProxyIterator(ta.Iterator[T]):
         
     | 
| 
       88 
     | 
    
         
            -
             
     | 
| 
       89 
     | 
    
         
            -
                def __init__(self, fn: ta.Callable[[], T]) -> None:
         
     | 
| 
       90 
     | 
    
         
            -
                    self._fn = fn
         
     | 
| 
       91 
     | 
    
         
            -
             
     | 
| 
       92 
     | 
    
         
            -
                def __iter__(self) -> ta.Self:
         
     | 
| 
       93 
     | 
    
         
            -
                    return self
         
     | 
| 
       94 
     | 
    
         
            -
             
     | 
| 
       95 
     | 
    
         
            -
                def __next__(self) -> T:
         
     | 
| 
       96 
     | 
    
         
            -
                    return self._fn()
         
     | 
| 
       97 
     | 
    
         
            -
             
     | 
| 
       98 
     | 
    
         
            -
             
     | 
| 
       99 
     | 
    
         
            -
            class PrefetchIterator(ta.Iterator[T]):
         
     | 
| 
       100 
     | 
    
         
            -
             
     | 
| 
       101 
     | 
    
         
            -
                def __init__(self, fn: ta.Callable[[], T] | None = None) -> None:
         
     | 
| 
       102 
     | 
    
         
            -
                    super().__init__()
         
     | 
| 
       103 
     | 
    
         
            -
             
     | 
| 
       104 
     | 
    
         
            -
                    self._fn = fn
         
     | 
| 
       105 
     | 
    
         
            -
                    self._deque: collections.deque[T] = collections.deque()
         
     | 
| 
       106 
     | 
    
         
            -
             
     | 
| 
       107 
     | 
    
         
            -
                def __iter__(self) -> ta.Self:
         
     | 
| 
       108 
     | 
    
         
            -
                    return self
         
     | 
| 
       109 
     | 
    
         
            -
             
     | 
| 
       110 
     | 
    
         
            -
                def push(self, item) -> None:
         
     | 
| 
       111 
     | 
    
         
            -
                    self._deque.append(item)
         
     | 
| 
       112 
     | 
    
         
            -
             
     | 
| 
       113 
     | 
    
         
            -
                def __next__(self) -> T:
         
     | 
| 
       114 
     | 
    
         
            -
                    try:
         
     | 
| 
       115 
     | 
    
         
            -
                        return self._deque.popleft()
         
     | 
| 
       116 
     | 
    
         
            -
                    except IndexError:
         
     | 
| 
       117 
     | 
    
         
            -
                        if self._fn is None:
         
     | 
| 
       118 
     | 
    
         
            -
                            raise StopIteration from None
         
     | 
| 
       119 
     | 
    
         
            -
                    return self._fn()
         
     | 
| 
       120 
     | 
    
         
            -
             
     | 
| 
       121 
     | 
    
         
            -
             
     | 
| 
       122 
     | 
    
         
            -
            class RetainIterator(ta.Iterator[T]):
         
     | 
| 
       123 
     | 
    
         
            -
             
     | 
| 
       124 
     | 
    
         
            -
                def __init__(self, fn: ta.Callable[[], T]) -> None:
         
     | 
| 
       125 
     | 
    
         
            -
                    super().__init__()
         
     | 
| 
       126 
     | 
    
         
            -
             
     | 
| 
       127 
     | 
    
         
            -
                    self._fn = fn
         
     | 
| 
       128 
     | 
    
         
            -
                    self._deque: collections.deque[T] = collections.deque()
         
     | 
| 
       129 
     | 
    
         
            -
             
     | 
| 
       130 
     | 
    
         
            -
                def __iter__(self) -> ta.Self:
         
     | 
| 
       131 
     | 
    
         
            -
                    return self
         
     | 
| 
       132 
     | 
    
         
            -
             
     | 
| 
       133 
     | 
    
         
            -
                def pop(self) -> None:
         
     | 
| 
       134 
     | 
    
         
            -
                    self._deque.popleft()
         
     | 
| 
       135 
     | 
    
         
            -
             
     | 
| 
       136 
     | 
    
         
            -
                def __next__(self) -> T:
         
     | 
| 
       137 
     | 
    
         
            -
                    item = self._fn()
         
     | 
| 
       138 
     | 
    
         
            -
                    self._deque.append(item)
         
     | 
| 
       139 
     | 
    
         
            -
                    return item
         
     | 
| 
       140 
     | 
    
         
            -
             
     | 
| 
       141 
     | 
    
         
            -
             
     | 
| 
       142 
     | 
    
         
            -
            def unzip(it: ta.Iterable[T], width: int | None = None) -> list:
         
     | 
| 
       143 
     | 
    
         
            -
                if width is None:
         
     | 
| 
       144 
     | 
    
         
            -
                    if not isinstance(it, PeekIterator):
         
     | 
| 
       145 
     | 
    
         
            -
                        it = PeekIterator(iter(it))
         
     | 
| 
       146 
     | 
    
         
            -
                    try:
         
     | 
| 
       147 
     | 
    
         
            -
                        width = len(it.peek())
         
     | 
| 
       148 
     | 
    
         
            -
                    except StopIteration:
         
     | 
| 
       149 
     | 
    
         
            -
                        return []
         
     | 
| 
       150 
     | 
    
         
            -
             
     | 
| 
       151 
     | 
    
         
            -
                its: list[PrefetchIterator[T]] = []
         
     | 
| 
       152 
     | 
    
         
            -
                running = True
         
     | 
| 
       153 
     | 
    
         
            -
             
     | 
| 
       154 
     | 
    
         
            -
                def next_fn(idx):
         
     | 
| 
       155 
     | 
    
         
            -
                    nonlocal running
         
     | 
| 
       156 
     | 
    
         
            -
                    if not running:
         
     | 
| 
       157 
     | 
    
         
            -
                        raise StopIteration
         
     | 
| 
       158 
     | 
    
         
            -
                    try:
         
     | 
| 
       159 
     | 
    
         
            -
                        items = next(it)  # type: ignore
         
     | 
| 
       160 
     | 
    
         
            -
                    except StopIteration:
         
     | 
| 
       161 
     | 
    
         
            -
                        running = False
         
     | 
| 
       162 
     | 
    
         
            -
                        raise
         
     | 
| 
       163 
     | 
    
         
            -
                    for item_idx, item in enumerate(items):
         
     | 
| 
       164 
     | 
    
         
            -
                        its[item_idx].push(item)
         
     | 
| 
       165 
     | 
    
         
            -
                    return next(its[idx])
         
     | 
| 
       166 
     | 
    
         
            -
             
     | 
| 
       167 
     | 
    
         
            -
                its.extend(PrefetchIterator(functools.partial(next_fn, idx)) for idx in range(width))
         
     | 
| 
       168 
     | 
    
         
            -
                return its
         
     | 
| 
       169 
     | 
    
         
            -
             
     | 
| 
       170 
     | 
    
         
            -
             
     | 
| 
       171 
     | 
    
         
            -
            def take(n: int, iterable: ta.Iterable[T]) -> list[T]:
         
     | 
| 
       172 
     | 
    
         
            -
                return list(itertools.islice(iterable, n))
         
     | 
| 
       173 
     | 
    
         
            -
             
     | 
| 
       174 
     | 
    
         
            -
             
     | 
| 
       175 
     | 
    
         
            -
            def chunk(n: int, iterable: ta.Iterable[T], strict: bool = False) -> ta.Iterator[list[T]]:
         
     | 
| 
       176 
     | 
    
         
            -
                iterator = iter(functools.partial(take, n, iter(iterable)), [])
         
     | 
| 
       177 
     | 
    
         
            -
                if strict:
         
     | 
| 
       178 
     | 
    
         
            -
                    def ret():
         
     | 
| 
       179 
     | 
    
         
            -
                        for chunk in iterator:
         
     | 
| 
       180 
     | 
    
         
            -
                            if len(chunk) != n:
         
     | 
| 
       181 
     | 
    
         
            -
                                raise ValueError('iterable is not divisible by n.')
         
     | 
| 
       182 
     | 
    
         
            -
                            yield chunk
         
     | 
| 
       183 
     | 
    
         
            -
                    return iter(ret())
         
     | 
| 
       184 
     | 
    
         
            -
                else:
         
     | 
| 
       185 
     | 
    
         
            -
                    return iterator
         
     | 
| 
       186 
     | 
    
         
            -
             
     | 
| 
       187 
     | 
    
         
            -
             
     | 
| 
       188 
     | 
    
         
            -
            def merge_on(
         
     | 
| 
       189 
     | 
    
         
            -
                    function: ta.Callable[[T], U],
         
     | 
| 
       190 
     | 
    
         
            -
                    *its: ta.Iterable[T],
         
     | 
| 
       191 
     | 
    
         
            -
            ) -> ta.Iterator[tuple[U, list[tuple[int, T]]]]:
         
     | 
| 
       192 
     | 
    
         
            -
                indexed_its = [
         
     | 
| 
       193 
     | 
    
         
            -
                    (
         
     | 
| 
       194 
     | 
    
         
            -
                        (function(item), it_idx, item)
         
     | 
| 
       195 
     | 
    
         
            -
                        for it_idx, item in zip(itertools.repeat(it_idx), it)
         
     | 
| 
       196 
     | 
    
         
            -
                    )
         
     | 
| 
       197 
     | 
    
         
            -
                    for it_idx, it in enumerate(its)
         
     | 
| 
       198 
     | 
    
         
            -
                ]
         
     | 
| 
       199 
     | 
    
         
            -
             
     | 
| 
       200 
     | 
    
         
            -
                grouped_indexed_its = itertools.groupby(
         
     | 
| 
       201 
     | 
    
         
            -
                    heapq.merge(*indexed_its),
         
     | 
| 
       202 
     | 
    
         
            -
                    key=lambda item_tuple: item_tuple[0],
         
     | 
| 
       203 
     | 
    
         
            -
                )
         
     | 
| 
       204 
     | 
    
         
            -
             
     | 
| 
       205 
     | 
    
         
            -
                return (
         
     | 
| 
       206 
     | 
    
         
            -
                    (fn_item, [(it_idx, item) for _, it_idx, item in grp])
         
     | 
| 
       207 
     | 
    
         
            -
                    for fn_item, grp in grouped_indexed_its
         
     | 
| 
       208 
     | 
    
         
            -
                )
         
     | 
| 
       209 
     | 
    
         
            -
             
     | 
| 
       210 
     | 
    
         
            -
             
     | 
| 
       211 
     | 
    
         
            -
            def expand_indexed_pairs(
         
     | 
| 
       212 
     | 
    
         
            -
                    seq: ta.Iterable[tuple[int, T]],
         
     | 
| 
       213 
     | 
    
         
            -
                    default: T,
         
     | 
| 
       214 
     | 
    
         
            -
                    *,
         
     | 
| 
       215 
     | 
    
         
            -
                    width: int | None = None,
         
     | 
| 
       216 
     | 
    
         
            -
            ) -> list[T]:
         
     | 
| 
       217 
     | 
    
         
            -
                width_ = width
         
     | 
| 
       218 
     | 
    
         
            -
                if width_ is None:
         
     | 
| 
       219 
     | 
    
         
            -
                    width_ = (max(idx for idx, _ in seq) + 1) if seq else 0
         
     | 
| 
       220 
     | 
    
         
            -
                result = [default] * width_
         
     | 
| 
       221 
     | 
    
         
            -
                for idx, value in seq:
         
     | 
| 
       222 
     | 
    
         
            -
                    if idx < width_:
         
     | 
| 
       223 
     | 
    
         
            -
                        result[idx] = value
         
     | 
| 
       224 
     | 
    
         
            -
                return result
         
     | 
| 
       225 
     | 
    
         
            -
             
     | 
| 
       226 
     | 
    
         
            -
             
     | 
| 
       227 
     | 
    
         
            -
            ##
         
     | 
| 
       228 
     | 
    
         
            -
            # https://docs.python.org/3/library/itertools.html#itertools-recipes
         
     | 
| 
       229 
     | 
    
         
            -
             
     | 
| 
       230 
     | 
    
         
            -
             
     | 
| 
       231 
     | 
    
         
            -
            def sliding_window(it: ta.Iterable[T], n: int) -> ta.Iterator[tuple[T, ...]]:
         
     | 
| 
       232 
     | 
    
         
            -
                # sliding_window('ABCDEFG', 4) -> ABCD BCDE CDEF DEFG
         
     | 
| 
       233 
     | 
    
         
            -
                iterator = iter(it)
         
     | 
| 
       234 
     | 
    
         
            -
                window = collections.deque(itertools.islice(iterator, n - 1), maxlen=n)
         
     | 
| 
       235 
     | 
    
         
            -
                for x in iterator:
         
     | 
| 
       236 
     | 
    
         
            -
                    window.append(x)
         
     | 
| 
       237 
     | 
    
         
            -
                    yield tuple(window)
         
     | 
| 
       238 
     | 
    
         
            -
             
     | 
| 
       239 
     | 
    
         
            -
             
     | 
| 
       240 
     | 
    
         
            -
            ##
         
     | 
| 
       241 
     | 
    
         
            -
             
     | 
| 
       242 
     | 
    
         
            -
             
     | 
| 
       243 
     | 
    
         
            -
            @dc.dataclass()
         
     | 
| 
       244 
     | 
    
         
            -
            class UniqueStats:
         
     | 
| 
       245 
     | 
    
         
            -
                key: ta.Any
         
     | 
| 
       246 
     | 
    
         
            -
                num_seen: int
         
     | 
| 
       247 
     | 
    
         
            -
                first_idx: int
         
     | 
| 
       248 
     | 
    
         
            -
                last_idx: int
         
     | 
| 
       249 
     | 
    
         
            -
             
     | 
| 
       250 
     | 
    
         
            -
             
     | 
| 
       251 
     | 
    
         
            -
            @dc.dataclass(frozen=True)
         
     | 
| 
       252 
     | 
    
         
            -
            class UniqueItem(ta.Generic[T]):
         
     | 
| 
       253 
     | 
    
         
            -
                idx: int
         
     | 
| 
       254 
     | 
    
         
            -
                item: T
         
     | 
| 
       255 
     | 
    
         
            -
                stats: UniqueStats
         
     | 
| 
       256 
     | 
    
         
            -
                out: lang.Maybe[T]
         
     | 
| 
       257 
     | 
    
         
            -
             
     | 
| 
       258 
     | 
    
         
            -
             
     | 
| 
       259 
     | 
    
         
            -
            class UniqueIterator(ta.Iterator[UniqueItem[T]]):
         
     | 
| 
       260 
     | 
    
         
            -
                def __init__(
         
     | 
| 
       261 
     | 
    
         
            -
                        self,
         
     | 
| 
       262 
     | 
    
         
            -
                        it: ta.Iterable[T],
         
     | 
| 
       263 
     | 
    
         
            -
                        keyer: ta.Callable[[T], ta.Any] = lang.identity,
         
     | 
| 
       264 
     | 
    
         
            -
                ) -> None:
         
     | 
| 
       265 
     | 
    
         
            -
                    super().__init__()
         
     | 
| 
       266 
     | 
    
         
            -
                    self._it = enumerate(it)
         
     | 
| 
       267 
     | 
    
         
            -
                    self._keyer = keyer
         
     | 
| 
       268 
     | 
    
         
            -
             
     | 
| 
       269 
     | 
    
         
            -
                    self.stats: dict[ta.Any, UniqueStats] = {}
         
     | 
| 
       270 
     | 
    
         
            -
             
     | 
| 
       271 
     | 
    
         
            -
                def __next__(self) -> UniqueItem[T]:
         
     | 
| 
       272 
     | 
    
         
            -
                    idx, item = next(self._it)
         
     | 
| 
       273 
     | 
    
         
            -
                    key = self._keyer(item)
         
     | 
| 
       274 
     | 
    
         
            -
             
     | 
| 
       275 
     | 
    
         
            -
                    try:
         
     | 
| 
       276 
     | 
    
         
            -
                        stats = self.stats[key]
         
     | 
| 
       277 
     | 
    
         
            -
             
     | 
| 
       278 
     | 
    
         
            -
                    except KeyError:
         
     | 
| 
       279 
     | 
    
         
            -
                        stats = self.stats[key] = UniqueStats(
         
     | 
| 
       280 
     | 
    
         
            -
                            key,
         
     | 
| 
       281 
     | 
    
         
            -
                            num_seen=1,
         
     | 
| 
       282 
     | 
    
         
            -
                            first_idx=idx,
         
     | 
| 
       283 
     | 
    
         
            -
                            last_idx=idx,
         
     | 
| 
       284 
     | 
    
         
            -
                        )
         
     | 
| 
       285 
     | 
    
         
            -
                        return UniqueItem(
         
     | 
| 
       286 
     | 
    
         
            -
                            idx,
         
     | 
| 
       287 
     | 
    
         
            -
                            item,
         
     | 
| 
       288 
     | 
    
         
            -
                            stats,
         
     | 
| 
       289 
     | 
    
         
            -
                            lang.just(item),
         
     | 
| 
       290 
     | 
    
         
            -
                        )
         
     | 
| 
       291 
     | 
    
         
            -
             
     | 
| 
       292 
     | 
    
         
            -
                    else:
         
     | 
| 
       293 
     | 
    
         
            -
                        stats.num_seen += 1
         
     | 
| 
       294 
     | 
    
         
            -
                        stats.last_idx = idx
         
     | 
| 
       295 
     | 
    
         
            -
                        return UniqueItem(
         
     | 
| 
       296 
     | 
    
         
            -
                            idx,
         
     | 
| 
       297 
     | 
    
         
            -
                            item,
         
     | 
| 
       298 
     | 
    
         
            -
                            stats,
         
     | 
| 
       299 
     | 
    
         
            -
                            lang.empty(),
         
     | 
| 
       300 
     | 
    
         
            -
                        )
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     | 
| 
         
            File without changes
         
     |