Changeset - ed0bc469ce5a
[Not reviewed]
0 2 0
Ben Sturmfels (bsturmfels) - 2 years ago 2022-02-04 08:15:11
ben@sturm.com.au
reconcile: Add type checking information to new prototype reconcilers.
2 files changed with 17 insertions and 13 deletions:
0 comments (0 inline, 0 general)
conservancy_beancount/reconcile/helper.py
Show inline comments
...
 
@@ -20,19 +20,21 @@ import datetime
 
import io
 
import tempfile
 
import textwrap
 
import typing
 
from typing import List
 
import os
 

	
 
from beancount import loader
 
from beancount.query.query import run_query
 

	
 

	
 
def end_of_month(date):
 
def end_of_month(date: datetime.date) -> datetime.date:
 
    """Given a date, return the last day of the month."""
 
    # Using 'day' replaces, rather than adds.
 
    return date + relativedelta(day=31)
 

	
 

	
 
def format_record_for_grep(row, homedir):
 
def format_record_for_grep(row: typing.List, homedir: str) -> typing.List:
 
    """Return a line in a grep-style.
 

	
 
    This is so the line can be fed into Emacs grep-mode for quickly jumping to
...
 
@@ -42,7 +44,7 @@ def format_record_for_grep(row, homedir):
 
    return [f'{file}:{row[1]}:'] + row[2:]
 

	
 

	
 
def max_column_widths(rows):
 
def max_column_widths(rows: List) -> List[int]:
 
    """Return the max width for each column in a table of data."""
 
    if not rows:
 
        return []
...
 
@@ -55,7 +57,7 @@ def max_column_widths(rows):
 
        return maxes
 

	
 

	
 
def tabulate(rows, headers=None):
 
def tabulate(rows: List, headers: List=None) -> str:
 
    """Format a table of data as a string.
 

	
 
    Implemented here to avoid adding dependency on "tabulate" package.
...
 
@@ -101,8 +103,9 @@ else:
 
    if not (args.cur_end_date and args.prev_end_date):
 
        parser.error(' --prev-end-date and --cur-end-date must be used together')
 
    preDate = args.prev_end_date
 
    lastDateInPeriod = args.cur_end_date
 
    month = lastDateInPeriod.strftime('%Y-%m')
 
    lastDateInPeriod = args.cur_end_date.isoformat()
 
    month = args.cur_end_date.strftime('%Y-%m')
 
grep_output_file: typing.IO
 
if args.grep_output_filename:
 
    grep_output_file = open(args.grep_output_filename, 'w')
 
else:
...
 
@@ -168,7 +171,7 @@ for desc, query in QUERIES.items():
 
    if not rrows:
 
        print(f'{desc:<55} {"N/A":>11}')
 
    elif desc.startswith('04'):
 
        homedir = os.getenv('HOME')
 
        homedir = os.getenv('HOME', '')
 
        print(f'{desc}\n   See {grep_output_file.name}')
 
        grep_rows = [format_record_for_grep(row, homedir) for row in rrows]
 
        print(tabulate(grep_rows), file=grep_output_file)
conservancy_beancount/reconcile/prototype_amex_reconciler.py
Show inline comments
...
 
@@ -10,14 +10,15 @@ import argparse
 
import csv
 
import datetime
 
import decimal
 
from typing import Dict, List, Tuple
 

	
 
from beancount import loader
 
from beancount.query.query import run_query
 
from thefuzz import fuzz
 
from thefuzz import fuzz  # type: ignore
 

	
 
# NOTE: Statement doesn't seem to give us a running balance or a final total.
 

	
 
def standardize_amex_record(row):
 
def standardize_amex_record(row: Dict) -> Dict:
 
    return {
 
        'date': datetime.datetime.strptime(row['Date'], '%m/%d/%Y').date(),
 
        'amount': -1 * decimal.Decimal(row['Amount']),
...
 
@@ -25,7 +26,7 @@ def standardize_amex_record(row):
 
    }
 

	
 

	
 
def standardize_beancount_record(row):
 
def standardize_beancount_record(row) -> Dict:  # type: ignore[no-untyped-def]
 
    return {
 
        'date': row.date,
 
        'amount': row.number_cost_position,
...
 
@@ -33,15 +34,15 @@ def standardize_beancount_record(row):
 
    }
 

	
 

	
 
def format_record(record):
 
def format_record(record: Dict) -> str:
 
    return f"{record['date'].isoformat()}: {record['amount']:>8} {record['payee'][:20]:<20}"
 

	
 

	
 
def sort_records(records):
 
def sort_records(records: List) -> List:
 
    return sorted(records, key=lambda x: (x['date'], x['amount']))
 

	
 

	
 
def records_match(r1, r2):
 
def records_match(r1: Dict, r2: Dict) -> Tuple[bool, str]:
 
    """Do these records represent the same transaction?"""
 
    date_matches = r1['date'] >= r2['date'] - datetime.timedelta(days=1) and r1['date'] <= r2['date'] + datetime.timedelta(days=1)
 
    amount_matches = r1['amount'] == r2['amount']
0 comments (0 inline, 0 general)