Skip to content

Commit 210ea80

Browse files
committed
New utility to cache and re-access iterators
1 parent a7b731d commit 210ea80

File tree

2 files changed

+50
-0
lines changed

2 files changed

+50
-0
lines changed

eth/_utils/generator.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import itertools
2+
from typing import (
3+
Generic,
4+
Iterable,
5+
Iterator,
6+
List,
7+
TypeVar,
8+
)
9+
10+
11+
TItem = TypeVar('TItem')
12+
13+
14+
class CachedIterable(Generic[TItem], Iterable[TItem]):
15+
def __init__(self, iterator: Iterable[TItem]) -> None:
16+
self._cached_results: List[TItem] = []
17+
self._iterator = iterator
18+
19+
def __iter__(self) -> Iterator[TItem]:
20+
return itertools.chain(self._cached_results, self._cache_and_yield())
21+
22+
def _cache_and_yield(self) -> Iterable[TItem]:
23+
for item in self._iterator:
24+
self._cached_results.append(item)
25+
yield item
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
from eth._utils.generator import CachedIterable
2+
3+
from eth_utils.toolz import (
4+
first,
5+
nth,
6+
)
7+
import itertools
8+
9+
10+
def test_cached_generator():
11+
use_once = itertools.count()
12+
repeated_use = CachedIterable(use_once)
13+
14+
for find_val in [1, 0, 10, 5]:
15+
assert find_val == nth(find_val, repeated_use)
16+
17+
18+
def test_laziness():
19+
def crash_after_first_val():
20+
yield 1
21+
raise Exception("oops, iterated past first value")
22+
23+
repeated_use = CachedIterable(crash_after_first_val())
24+
assert first(repeated_use) == 1
25+
assert first(repeated_use) == 1

0 commit comments

Comments
 (0)