Changeset - 8d584734ec0c
[Not reviewed]
0 2 0
Brett Smith - 4 years ago 2020-04-21 19:24:04
brettcsmith@brettcsmith.org
data: Add Posting.from_entries() method.
2 files changed with 39 insertions and 0 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/data.py
Show inline comments
...
 
@@ -37,12 +37,13 @@ from typing import (
 
    Optional,
 
    Sequence,
 
    Union,
 
)
 

	
 
from .beancount_types import (
 
    Directive,
 
    MetaKey,
 
    MetaValue,
 
    Posting as BasePosting,
 
    Transaction,
 
)
 

	
...
 
@@ -291,12 +292,25 @@ class Posting(BasePosting):
 
    @classmethod
 
    def from_txn(cls, txn: Transaction) -> Iterable['Posting']:
 
        """Yield an enhanced Posting object for every posting in the transaction"""
 
        for index, post in enumerate(txn.postings):
 
            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,
 
               *preds: Callable[[Account], Optional[bool]],
 
) -> Amount:
 
    """Return the balance of specified postings in a transaction.
 

	
tests/test_data_posting.py
Show inline comments
...
 
@@ -15,12 +15,14 @@
 
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 

	
 
import pytest
 

	
 
from . import testutil
 

	
 
from beancount.core import data as bc_data
 

	
 
from conservancy_beancount import data
 

	
 
@pytest.fixture
 
def simple_txn(index=None, key=None):
 
    return testutil.Transaction(note='txn note', postings=[
 
        ('Assets:Cash', 5),
...
 
@@ -54,6 +56,29 @@ def test_deleting_metadata_propagates_to_source(simple_txn):
 

	
 
def test_from_txn(simple_txn):
 
    for source, post in zip(simple_txn.postings, data.Posting.from_txn(simple_txn)):
 
        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_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
0 comments (0 inline, 0 general)