From 5706273bbe72aa84f30a84e08a7d444a06b2c349 2020-06-12 17:24:25 From: Brett Smith Date: 2020-06-12 17:24:25 Subject: [PATCH] accrual: Clean up types and imports. Mostly I wanted to write the documentation about groups, and then I kept pulling the thread. --- diff --git a/conservancy_beancount/reports/accrual.py b/conservancy_beancount/reports/accrual.py index f68d1abf31646df12606b95205af8b55c6544943..806b1460a9a5a2200cee27952a3e1bccec9dda7d 100644 --- a/conservancy_beancount/reports/accrual.py +++ b/conservancy_beancount/reports/accrual.py @@ -70,7 +70,6 @@ import collections import datetime import enum import logging -import re import sys import urllib.parse as urlparse @@ -119,9 +118,7 @@ from .. import rtutil PROGNAME = 'accrual-report' -CompoundAmount = TypeVar('CompoundAmount', data.Amount, core.Balance) -PostGroups = Mapping[Optional[MetaValue], 'AccrualPostings'] -RTObject = Mapping[str, str] +PostGroups = Mapping[Optional[str], 'AccrualPostings'] T = TypeVar('T') logger = logging.getLogger('conservancy_beancount.reports.accrual') @@ -213,7 +210,7 @@ class AccrualPostings(core.RelatedPostings): if pred(post) and 'entity' in post.meta ) - def make_consistent(self) -> Iterator[Tuple[MetaValue, 'AccrualPostings']]: + def make_consistent(self) -> Iterator[Tuple[str, 'AccrualPostings']]: account_ok = isinstance(self.account, str) entity_ok = isinstance(self.entity, str) # `'/' in self.invoice` is just our heuristic to ensure that the @@ -221,7 +218,10 @@ class AccrualPostings(core.RelatedPostings): # value like "FIXME". It can be refined if needed. invoice_ok = isinstance(self.invoice, str) and '/' in self.invoice if account_ok and entity_ok and invoice_ok: - yield (self.invoice, self) + # mypy loses track of the fact that self.invoice must be a str in + # this case (gated on the invoice_ok boolean) and complains it + # doesn't match the type of the return value. + yield (self.invoice, self) # type:ignore[misc] return groups = collections.defaultdict(list) for post in self: @@ -696,6 +696,14 @@ def main(arglist: Optional[Sequence[str]]=None, if not postings: logger.warning("no matching entries found to report") returncode |= ReturnFlag.NOTHING_TO_REPORT + # groups is a mapping of metadata value strings to AccrualPostings. + # The keys are basically arbitrary, the report classes don't rely on them, + # but they do help symbolize what's being grouped. + # For the outgoing approval report, groups maps rt-id link strings to + # associated accruals. + # For all other reports, groups starts by grouping postings together by + # invoice link string, then uses AccrualReport.make_consistent() to split + # out groups that need it. groups: PostGroups if args.report_type is None or args.report_type is ReportType.OUTGOING: groups = dict(AccrualPostings.group_by_first_meta_link(postings, 'rt-id'))