data: Add Posting.from_entries() method.

This commit is contained in:
Brett Smith 2020-04-21 15:24:04 -04:00
parent 3000aeee09
commit 8d584734ec
2 changed files with 39 additions and 0 deletions

View file

@ -40,6 +40,7 @@ from typing import (
) )
from .beancount_types import ( from .beancount_types import (
Directive,
MetaKey, MetaKey,
MetaValue, MetaValue,
Posting as BasePosting, Posting as BasePosting,
@ -294,6 +295,19 @@ class Posting(BasePosting):
for index, post in enumerate(txn.postings): for index, post in enumerate(txn.postings):
yield cls.from_beancount(txn, index, post) yield cls.from_beancount(txn, index, post)
@classmethod
def from_entries(cls, entries: Iterable[Directive]) -> Iterable['Posting']:
"""Yield an enhanced Posting object for every posting in these entries"""
for entry in entries:
# Because Beancount's own Transaction class isn't type-checkable,
# we can't statically check this. Might as well rely on duck
# typing while we're at it: just try to yield postings from
# everything, and ignore entries that lack a postings attribute.
try:
yield from cls.from_txn(entry) # type:ignore[arg-type]
except AttributeError:
pass
def balance_of(txn: Transaction, def balance_of(txn: Transaction,
*preds: Callable[[Account], Optional[bool]], *preds: Callable[[Account], Optional[bool]],

View file

@ -18,6 +18,8 @@ import pytest
from . import testutil from . import testutil
from beancount.core import data as bc_data
from conservancy_beancount import data from conservancy_beancount import data
@pytest.fixture @pytest.fixture
@ -57,3 +59,26 @@ def test_from_txn(simple_txn):
assert all(source[x] == post[x] for x in range(len(source) - 1)) assert all(source[x] == post[x] for x in range(len(source) - 1))
assert isinstance(post.account, data.Account) assert isinstance(post.account, data.Account)
assert post.meta['note'] # Only works with PostingMeta assert post.meta['note'] # Only works with PostingMeta
def test_from_entries_two_txns(simple_txn):
entries = [simple_txn, simple_txn]
sources = [post for txn in entries for post in txn.postings]
for source, post in zip(sources, data.Posting.from_entries(entries)):
assert all(source[x] == post[x] for x in range(len(source) - 1))
assert isinstance(post.account, data.Account)
assert post.meta['note'] # Only works with PostingMeta
def test_from_entries_mix_txns_and_other_directives(simple_txn):
meta = {
'filename': __file__,
'lineno': 75,
}
entries = [
bc_data.Commodity(meta, testutil.FY_START_DATE, 'EUR'),
bc_data.Commodity(meta, testutil.FY_START_DATE, 'USD'),
simple_txn,
]
for source, post in zip(simple_txn.postings, data.Posting.from_entries(entries)):
assert all(source[x] == post[x] for x in range(len(source) - 1))
assert isinstance(post.account, data.Account)
assert post.meta['note'] # Only works with PostingMeta