filters: Add iter_unique() function.

This commit is contained in:
Brett Smith 2020-06-11 09:17:05 -04:00
parent 9c33517583
commit e3dceb601c
3 changed files with 21 additions and 11 deletions

View file

@ -24,9 +24,13 @@ from . import rtutil
from typing import ( from typing import (
cast, cast,
Hashable,
Iterable, Iterable,
Iterator,
Optional, Optional,
Pattern, Pattern,
Set,
TypeVar,
Union, Union,
) )
from .beancount_types import ( from .beancount_types import (
@ -37,6 +41,8 @@ from .beancount_types import (
Transaction, Transaction,
) )
# Saying Optional works around <https://github.com/python/mypy/issues/8768>.
HashT = TypeVar('HashT', bound=Optional[Hashable])
Postings = Iterable[data.Posting] Postings = Iterable[data.Posting]
Regexp = Union[str, Pattern] Regexp = Union[str, Pattern]
@ -72,6 +78,13 @@ def filter_for_rt_id(postings: Postings, ticket_id: Union[int, str]) -> Postings
regexp = rtutil.RT.metadata_regexp(ticket_id, first_link_only=True) regexp = rtutil.RT.metadata_regexp(ticket_id, first_link_only=True)
return filter_meta_match(postings, 'rt-id', regexp) return filter_meta_match(postings, 'rt-id', regexp)
def iter_unique(seq: Iterable[HashT]) -> Iterator[HashT]:
seen: Set[HashT] = set()
for item in seq:
if item not in seen:
seen.add(item)
yield item
def remove_opening_balance_txn(entries: Entries) -> Optional[Transaction]: def remove_opening_balance_txn(entries: Entries) -> Optional[Transaction]:
"""Remove an opening balance transaction from entries returned by Beancount """Remove an opening balance transaction from entries returned by Beancount

View file

@ -207,17 +207,11 @@ class AccrualPostings(core.RelatedPostings):
return item1 if all_same else self.INCONSISTENT return item1 if all_same else self.INCONSISTENT
def entities(self, pred: Callable[[data.Posting], bool]=bool) -> Iterator[MetaValue]: def entities(self, pred: Callable[[data.Posting], bool]=bool) -> Iterator[MetaValue]:
seen: Set[MetaValue] = set() return filters.iter_unique(
for post in self: post.meta['entity']
if pred(post): for post in self
try: if pred(post) and 'entity' in post.meta
entity = post.meta['entity'] )
except KeyError:
pass
else:
if entity not in seen:
yield entity
seen.add(entity)
def first_links(self, key: MetaKey, default: Optional[str]=None) -> Iterator[Optional[str]]: def first_links(self, key: MetaKey, default: Optional[str]=None) -> Iterator[Optional[str]]:
return (post.meta.first_link(key, default) for post in self) return (post.meta.first_link(key, default) for post in self)

View file

@ -183,3 +183,6 @@ def test_audit_date(entry):
assert actual is None assert actual is None
else: else:
assert actual == entry.date assert actual == entry.date
def test_iter_unique():
assert list(filters.iter_unique('1213231')) == list('123')