Changeset - 639a41b7828b
[Not reviewed]
0 1 1
Brett Smith - 4 years ago 2020-10-06 14:38:39
brettcsmith@brettcsmith.org
sort_entries: New tool.
2 files changed with 102 insertions and 1 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/tools/sort_entries.py
Show inline comments
 
new file 100644
 
#!/usr/bin/env python3
 
"""sort_entries.py - Consistently sort and format Beancount entries
 

	
 
This is useful to use as a preprocessing step before comparing entries with
 
tools like ``diff``.
 
"""
 
# Copyright © 2020 Brett Smith
 
#
 
# This program is free software: you can redistribute it and/or modify
 
# it under the terms of the GNU Affero General Public License as published by
 
# the Free Software Foundation, either version 3 of the License, or
 
# (at your option) any later version.
 
#
 
# This program is distributed in the hope that it will be useful,
 
# but WITHOUT ANY WARRANTY; without even the implied warranty of
 
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
# GNU Affero General Public License for more details.
 
#
 
# You should have received a copy of the GNU Affero General Public License
 
# along with this program.  If not, see <https://www.gnu.org/licenses/>.
 

	
 
import argparse
 
import logging
 
import os
 
import sys
 

	
 
from pathlib import Path
 

	
 
from beancount.core import display_context as bc_dcontext
 
from beancount import loader as bc_loader
 
from beancount.parser import printer as bc_printer
 

	
 
from typing import (
 
    Hashable,
 
    Optional,
 
    Sequence,
 
    TextIO,
 
)
 
from ..beancount_types import (
 
    Directive,
 
    Entries,
 
    Errors,
 
)
 

	
 
from .. import cliutil
 

	
 
PROGNAME = 'bean-sort'
 
logger = logging.getLogger('conservancy_beancount.tools.sort_entries')
 

	
 
def parse_arguments(arglist: Optional[Sequence[str]]=None) -> argparse.Namespace:
 
    parser = argparse.ArgumentParser(prog=PROGNAME)
 
    cliutil.add_version_argument(parser)
 
    cliutil.add_loglevel_argument(parser)
 
    parser.add_argument(
 
        '--quiet', '-q',
 
        action='store_true',
 
        help="""Suppress Beancount errors
 
""")
 
    parser.add_argument(
 
        'paths',
 
        metavar='PATH',
 
        type=Path,
 
        nargs=argparse.ONE_OR_MORE,
 
        help="""Beancount path(s) to read entries from
 
""")
 
    return parser.parse_args(arglist)
 

	
 
def entry_sorter(entry: Directive) -> Hashable:
 
    type_name = type(entry).__name__
 
    if type_name == 'Transaction':
 
        return (entry.date, type_name, entry.narration, entry.payee or '')  # type:ignore[attr-defined]
 
    else:
 
        return (entry.date, type_name)
 

	
 
def main(arglist: Optional[Sequence[str]]=None,
 
         stdout: TextIO=sys.stdout,
 
         stderr: TextIO=sys.stderr,
 
) -> int:
 
    args = parse_arguments(arglist)
 
    cliutil.set_loglevel(logger, args.loglevel)
 

	
 
    entries: Entries = []
 
    errors: Errors = []
 
    for path in args.paths:
 
        new_entries, new_errors, _ = bc_loader.load_file(path)
 
        entries.extend(new_entries)
 
        errors.extend(new_errors)
 
    entries.sort(key=entry_sorter)
 
    if not args.quiet:
 
        for error in errors:
 
            bc_printer.print_error(error, file=stderr)
 
    dcontext = bc_dcontext.DisplayContext()
 
    dcontext.set_commas(True)
 
    bc_printer.print_entries(entries, dcontext, file=stdout)
 
    return os.EX_DATAERR if errors and not args.quiet else os.EX_OK
 

	
 
entry_point = cliutil.make_entry_point(__name__, PROGNAME)
 

	
 
if __name__ == '__main__':
 
    exit(entry_point())
setup.py
Show inline comments
...
 
@@ -5,7 +5,7 @@ from setuptools import setup
 
setup(
 
    name='conservancy_beancount',
 
    description="Plugin, library, and reports for reading Conservancy's books",
 
    version='1.11.1',
 
    version='1.12.0',
 
    author='Software Freedom Conservancy',
 
    author_email='info@sfconservancy.org',
 
    license='GNU AGPLv3+',
...
 
@@ -40,6 +40,7 @@ setup(
 
            'accrual-report = conservancy_beancount.reports.accrual:entry_point',
 
            'assemble-audit-reports = conservancy_beancount.tools.audit_report:entry_point',
 
            'balance-sheet-report = conservancy_beancount.reports.balance_sheet:entry_point',
 
            'bean-sort = conservancy_beancount.tools.sort_entries:entry_point',
 
            'extract-odf-links = conservancy_beancount.tools.extract_odf_links:entry_point',
 
            'fund-report = conservancy_beancount.reports.fund:entry_point',
 
            'ledger-report = conservancy_beancount.reports.ledger:entry_point',
0 comments (0 inline, 0 general)