示例#1
0
def format_posting(posting: Posting, indent: str = '  ') -> str:
    printer = beancount.parser.printer.EntryPrinter()
    flag_account, position_str, weight_str = printer.render_posting_strings(
        posting)
    oss = io.StringIO()
    oss.write(('%s%s  %s' % (indent, flag_account, position_str)).rstrip() +
              '\n')
    if posting.meta:
        printer.write_metadata(posting.meta, oss, '  ' + indent)
    return oss.getvalue()
示例#2
0
    def get_diff(self):
        if self._cached_diff is not None:
            return self._cached_diff

        change_sets = []
        new_entries = []
        old_entries = []

        printer = beancount.parser.printer.EntryPrinter()

        for filename, changed_entries in self.changed_entries.items():
            changed_entries.sort(key=lambda x: float('inf')
                                 if x[0] is None else x[0].meta['lineno'])
            _, lines = self.journal_editor.get_journal_lines(filename)
            change_sets_builder = FileChangeSetsBuilder(filename=filename,
                                                        lines=lines)
            for old_entry, new_entry in changed_entries:
                if new_entry is None:
                    # Remove entry
                    _, _, line_range = self.journal_editor.get_entry_line_range(
                        old_entry)
                    start_line = line_range[0]

                    # Move start line up until non-whitespace line
                    while start_line > 0 and not lines[start_line - 1].strip():
                        start_line -= 1

                    builder = change_sets_builder.add_builder(
                        (start_line, line_range[1]))
                    builder.delete_until(line_range[1])
                    old_entries.append(old_entry)
                elif old_entry is None:
                    # Add new entry

                    _, _, line_range = self.journal_editor.get_append_line_range(
                        filename)
                    builder = change_sets_builder.add_builder(line_range)
                    builder.ensure_blank_line()
                    new_entry = builder.set_metadata(new_entry)
                    if isinstance(new_entry, Transaction):
                        new_postings = []
                        cur_lineno = new_entry.meta['lineno'] + 1 + len(
                            new_entry.meta.keys() - META_IGNORE)
                        new_postings = []
                        for posting in new_entry.postings:
                            posting = builder.set_metadata(posting, cur_lineno)
                            cur_lineno += 1 + len(posting.meta.keys() -
                                                  META_IGNORE)
                            new_postings.append(posting)
                        new_entry = new_entry._replace(postings=new_postings)
                    new_entries.append(new_entry)
                    added_lines = printer(new_entry).strip('\n').split('\n')
                    added_lines = [x.rstrip() for x in added_lines]
                    builder.add_lines(added_lines)

                else:
                    # Change entry

                    _, _, line_range = self.journal_editor.get_entry_line_range(
                        old_entry)
                    builder = change_sets_builder.add_builder(line_range)
                    old_print_result = printer(old_entry).split('\n')
                    new_print_result = printer(new_entry).split('\n')
                    new_entry = builder.set_metadata(new_entry)
                    if old_print_result[0] == new_print_result[0]:
                        # First line is the same
                        builder.keep_line()
                    else:
                        builder.replace_line(new_print_result[0].rstrip())
                    compute_metadata_changes(builder=builder,
                                             old_meta=old_entry.meta,
                                             new_meta=new_entry.meta,
                                             indent=2)
                    assert isinstance(old_entry, Transaction) == isinstance(
                        new_entry, Transaction)
                    if isinstance(old_entry, Transaction):
                        # handle postings
                        next_old_posting_i = 0
                        new_postings = []
                        for new_posting in new_entry.postings:
                            new_posting = builder.set_metadata(new_posting)
                            new_postings.append(new_posting)
                            if next_old_posting_i < len(old_entry.postings):
                                old_posting = old_entry.postings[
                                    next_old_posting_i]
                                # posting replaces old_posting
                                compute_posting_changes(
                                    builder=builder,
                                    old_posting=old_posting,
                                    new_posting=new_posting)
                                next_old_posting_i += 1
                            else:
                                new_posting_lines = []
                                new_posting_lines.append(
                                    get_posting_line(new_posting))
                                oss = io.StringIO()
                                printer.write_metadata(new_posting.meta,
                                                       oss,
                                                       prefix='    ')
                                metadata_text = oss.getvalue().strip('\n')
                                if metadata_text:
                                    new_posting_lines.extend(
                                        metadata_text.split('\n'))
                                builder.add_lines(new_posting_lines)
                        # Delete all remaining old postings
                        builder.delete_until(builder.line_range[1])

                        # Replace list of postings with postings containing updated filename and lineno
                        # information.
                        new_entry = new_entry._replace(postings=new_postings)
                    old_entries.append(old_entry)
                    new_entries.append(new_entry)
            change_sets.append(change_sets_builder.change_sets)
        self._cached_diff = change_sets, old_entries, new_entries
        return self._cached_diff
示例#3
0
 def format_metadata_line(key):
     oss = io.StringIO()
     printer.write_metadata({key: new_meta[key]}, oss, prefix=' ' * indent)
     return oss.getvalue().rstrip()