def set_metadata(self, x: Directive, lineno: Optional[int] = None): meta = dict({}, **(x.meta or {})) meta['filename'] = self.filename if lineno is None: lineno = self.new_lineno + 1 meta['lineno'] = lineno return x._replace(meta=meta)
def _partially_book_entry(orig_entry: Directive, booked_entry: Directive) -> Directive: """Computes a partially-booked entry. Given a pre-booking entry and a post-booking entry, returns a modified copy of the pre-booking entry that includes missing units. """ if not isinstance(orig_entry, Transaction): return orig_entry assert isinstance(booked_entry, Transaction) booked_postings_by_meta = dict() # type: Dict[int, List[Posting]] for posting in booked_entry.postings: meta = posting.meta if meta is None: continue booked_postings_by_meta.setdefault(id(meta), []).append(posting) partially_booked_postings = [] # type: List[Posting] empty_list = [] # type: List[Posting] for posting in orig_entry.postings: booked_matches = booked_postings_by_meta.get( id(posting.meta), empty_list) if len(booked_matches) != 1: partially_booked_postings.append(posting) continue booked_match = booked_matches[0] if posting.units is MISSING and booked_match.units is not MISSING: posting = posting._replace(units=booked_match.units) partially_booked_postings.append(posting) return orig_entry._replace(postings=partially_booked_postings)
def _format_entry(entry: Directive, currency_column: int) -> str: """Wrapper that strips unnecessary whitespace from format_entry.""" meta = { key: entry.meta[key] for key in entry.meta if not key.startswith("_") } entry = entry._replace(meta=meta) string = align(format_entry(entry), currency_column) string = string.replace("<class 'beancount.core.number.MISSING'>", "") return "\n".join((line.rstrip() for line in string.split("\n")))
def categorize_entry(catmap: Dict[Account, Cat], entry: data.Directive) -> Tuple[Cat]: """Assigns metadata to each posting.""" postings = [] for posting in entry.postings: category = catmap[posting.account] if category is None: category = Cat.OTHER if posting.cost is None else Cat.OTHERASSET meta = posting.meta.copy() if posting.meta else {} meta["category"] = category postings.append(posting._replace(meta=meta)) return entry._replace(postings=postings)
def merge_narration(entry: Directive, comment_narrations: Dict[str, Dict[int, str]]) -> Directive: if not isinstance(entry, Transaction): return entry narrations = [] for posting in entry.postings: if posting.meta: narration = posting.meta.get('narration') comment_narration = comment_narrations.get(posting.meta.get('filename')).get(posting.meta.get('lineno')) if narration is None and comment_narration: posting.meta['narration'] = comment_narration narration = comment_narration if narration: narrations.append(narration.strip()) if entry.narration: return entry return entry._replace(narration=' | '.join(narrations))
def serialise(entry: Directive) -> Any: """Serialise an entry.""" if not entry: return None ret = entry._asdict() ret["type"] = entry.__class__.__name__ if isinstance(entry, Transaction): ret["payee"] = entry.payee or "" if entry.tags: ret["narration"] += " " + " ".join(["#" + t for t in entry.tags]) if entry.links: ret["narration"] += " " + " ".join( ["^" + link for link in entry.links]) del ret["links"] del ret["tags"] ret["postings"] = [serialise(pos) for pos in entry.postings] elif ret["type"] == "Balance": amt = ret["amount"] ret["amount"] = {"number": str(amt.number), "currency": amt.currency} return ret