Beispiel #1
0
def print_field(t, field, matches=None, extras=None):
    if not extras:
        extras = {}
    pad_width = 12
    fieldname = extras.get(field, '  ' + field.title())
    line = TERM.clear_eol + '%s: %s' % (TERM.ljust(
        fieldname, pad_width, '.'), colorize_match(t, field.lower(), matches)
                                        or TERM.red('<none>'))
    print(line)
Beispiel #2
0
def print_field(t, field, matches=None, extras=None):
    if not extras:
        extras = {}
    pad_width = 12
    fieldname = extras.get(field, '  ' + field.title())
    line = TERM.clear_eol + '%s: %s' % (
        TERM.ljust(fieldname, pad_width, '.'),
        colorize_match(t, field.lower(), matches) or TERM.red('<none>')
    )
    print(line)
Beispiel #3
0
def print_field(t, field, matches=None, extras=None):
    if not extras:
        extras = {}
    pad_width = 12
    fieldname = extras.get(field, "  " + field.title())
    line = TERM.clear_eol + "%s: %s" % (
        TERM.ljust(fieldname, pad_width, "."),
        colorize_match(t, field.lower(), matches) or TERM.red("<none>"),
    )
    print(line)
Beispiel #4
0
def check_ruler(ruler, t):
    """Build fields status dict obtained by applying ruler to transaction."""
    extras = {}
    match, match_info = tags.match(ruler, t)
    for (key, val) in match_info.items():
        if not val:
            extras[key] = TERM.red("%s %s" % (TERM.KO, key.title()))
        else:
            extras[key] = TERM.green("%s %s" % (TERM.OK, key.title()))
    if not match:
        extras["category"] = TERM.red("%s Category" % TERM.KO)
    else:
        extras["category"] = TERM.green("%s Category" % TERM.OK)
    return match, extras
Beispiel #5
0
def check_ruler(ruler, t):
    """Build fields status dict obtained by applying ruler to transaction.
    """
    extras = {}
    match, match_info = tags.match(ruler, t)
    if not match:
        for (key, val) in match_info.iteritems():
            if not val:
                extras[key] = TERM.red('✖ %s' % key.title())
        extras['category'] = TERM.red('✖ Category')
    else:
        for field in ruler:
            extras[field] = TERM.green('✔ %s' % field.title())
        extras['category'] = TERM.green('✔ Category')
    return match, extras
Beispiel #6
0
def check_ruler(ruler, t):
    """Build fields status dict obtained by applying ruler to transaction.
    """
    extras = {}
    match, match_info = tags.match(ruler, t)
    for (key, val) in match_info.iteritems():
        if not val:
            extras[key] = TERM.red(u'%s %s' % (TERM.KO, key.title()))
        else:
            extras[key] = TERM.green(u'%s %s' % (TERM.OK, key.title()))
    if not match:
        extras['category'] = TERM.red(u'%s Category' % TERM.KO)
    else:
        extras['category'] = TERM.green(u'%s Category' % TERM.OK)
    return match, extras
Beispiel #7
0
def query_guru_ruler(t):
    """Define rules on a combination of fields. All rules must match
    corresponding fields for the ruler to be valid.
    """
    extras = sorted([k for (k, v) in t.items() if (v and not k.isdigit())])
    matchable_fields = sorted(
        set([x
             for x in t if t[x] and not x.isdigit()]) - {"category", "number"})

    guru_ruler = {}
    extras = {}
    field = True
    while field:
        # Enter field
        while True:
            # Update fields match indicators
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            field = quick_input("\nMatch on field",
                                sugg=matchable_fields,
                                clear=True).lower()
            regex = "*" in field
            field = field.strip("*")
            if not field or field in matchable_fields:
                break
        # Enter match
        while field:
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            existing_match = guru_ruler.get(field, "")
            ruler = quick_input(
                "\n%s match (%s)%s" % (
                    field.title(),
                    "regex" if regex else "chars",
                    " [%s]" % existing_match if existing_match else "",
                ),
                clear=True,
            )
            if ruler.isspace():  # remove field rule from ruler
                extras.pop(field, None)
                guru_ruler.pop(field, None)
            elif ruler:
                guru_ruler[field] = r"%s" % ruler if regex else re.escape(
                    ruler)
            match, extras = check_ruler(guru_ruler, t)
            if match:
                break
    return guru_ruler
Beispiel #8
0
def process_transaction(t, options):
    """Assign a category to a transaction.
    """
    cat, ruler = t['category'], None
    extras = {}
    if not t['category']:  # Grab category from json cache
        cat, ruler, _ = tags.find_tag_for(t)
        if cat:
            t['category'] = cat
            extras = {'category': '+ Category'}

    print('---\n' + TERM.clear_eol, end='')
    print_transaction(t, extras=extras)
    edit = False
    audit = options.get('audit', False)
    if t['category']:
        if audit:
            msg = "\nEdit '%s' category" % TERM.green(t['category'])
            edit = quick_input(msg, 'yN', vanish=True) == 'Y'
        if not edit:
            return t['category'], ruler

    # Query for category and overwrite category on screen
    if (not cat or edit) and not options.get('batch', False):
        t['category'] = query_cat(cat)
        extras = {'category': '✔ Category'} if not t['category'] else {}
        print(TERM.clear_last, end='')
        print_field(t, 'category', extras=extras)
    # Query ruler if category entered or edit
    if t['category']:
        ruler = query_ruler(t)
    return t['category'], ruler
Beispiel #9
0
def process_transaction(t, options):
    """Assign a category to a transaction.
    """
    cat, ruler = t['category'], None
    extras = {}

    if not t['category']:  # Grab category from json cache
        cat, ruler, _ = tags.find_tag_for(t)
        if cat:
            t['category'] = cat
            extras = {'category': '+ Category'}

    print('---\n' + TERM.clear_eol, end='')
    print_transaction(t, extras=extras)
    edit = options['force'] > 1 or (options['force']
                                    and t['category'] not in tags.TAGS)
    audit = options['audit']
    if t['category']:
        if audit:
            msg = "\nEdit '%s' category" % TERM.green(t['category'])
            edit = quick_input(msg, 'yN', vanish=True) == 'Y'
        if not edit:
            return t['category'], ruler

    # Query for category and overwrite category on screen
    if (not cat or edit) and not options['batch']:
        t['category'] = query_cat(cat)
        # Query ruler if category entered or edit
        if t['category']:
            ruler = query_ruler(t)
        extras = {'category': TERM.OK + ' Category'} if t['category'] else {}
        print(TERM.clear_last, end='')
        print_field(t, 'category', extras=extras)

    return t['category'], ruler
Beispiel #10
0
def process_transaction(t, options):
    """Assign a category to a transaction.
    """
    cat, ruler = t["category"], None
    extras = {}

    if not t["category"]:  # Grab category from json cache
        cat, ruler, _ = tags.find_tag_for(t)
        if cat:
            t["category"] = cat
            extras = {"category": "+ Category"}

    print("---\n" + TERM.clear_eol, end="")
    print_transaction(t, extras=extras)
    edit = options["force"] > 1 or (options["force"] and t["category"] not in tags.TAGS)
    audit = options["audit"]
    if t["category"]:
        if audit:
            msg = "\nEdit '%s' category" % TERM.green(t["category"])
            edit = quick_input(msg, "yN", clear=True) == "Y"
        if not edit:
            return t["category"], ruler

    # Query for category and overwrite category on screen
    if (not cat or edit) and not options["batch"]:
        t["category"] = query_cat(cat)
        # Query ruler if category entered or edit
        if t["category"]:
            ruler = query_ruler(t)
        extras = {"category": TERM.OK + " Category"} if t["category"] else {}
        print(TERM.clear_last, end="")
        print_field(t, "category", extras=extras)

    return t["category"], ruler
Beispiel #11
0
def colorize_match(t, field, matches=None):
    field_val = t[field]
    if not field_val:
        return None
    match = matches.get(field, '') if matches else ''
    seqmatch = SequenceMatcher(None, field_val, match)
    a, b, size = seqmatch.find_longest_match(0, len(field_val), 0, len(match))
    return (field_val[:a] + TERM.green(field_val[a:a + size]) +
            field_val[a + size:])
Beispiel #12
0
def colorize_match(t, field, matches=None):
    field_val = t[field]
    if not field_val:
        return None
    match = matches.get(field, '') if matches else ''
    seqmatch = SequenceMatcher(None, field_val, match)
    a, b, size = seqmatch.find_longest_match(0, len(field_val), 0, len(match))
    return (field_val[:a] + TERM.green(field_val[a:a + size]) +
            field_val[a + size:])
Beispiel #13
0
def query_ruler(t):
    """Prompt user to enter a valid matching ruler for transaction.
       First prompt is used to enter a basic ruler aka successive words to look
       for on payee line.
       This prompt can be skipped by pressing <Enter> to have access to guru
       ruler prompt, where ruler is a list of field/match to validate.
    """
    with TERM.fullscreen():
        extras = {'category': '? Category'}
        ok = False
        ruler = {}
        while True:
            print(TERM.move_y(0))
            print_transaction(t, extras=extras)
            if ok:
                break
            ruler = query_basic_ruler(t, tags.unrulify(ruler)) or \
                query_guru_ruler(t)
            ok, extras = check_ruler(ruler, t)
    return ruler
Beispiel #14
0
def query_ruler(t):
    """Prompt user to enter a valid matching ruler for transaction.
       First prompt is used to enter a basic ruler aka successive words to look
       for on payee line.
       This prompt can be skipped by pressing <Enter> to have access to guru
       ruler prompt, where ruler is a list of field/match to validate.
    """
    with TERM.fullscreen():
        extras = {}
        ok = False
        ruler = {}
        while True:
            print(TERM.move_y(0))
            print_transaction(t, extras=extras)
            if ok:
                break
            ruler = query_basic_ruler(t, tags.unrulify(ruler)) or query_guru_ruler(t)
            ok, extras = check_ruler(ruler, t)

    return ruler
Beispiel #15
0
def query_guru_ruler(t):
    """Define rules on a combination of fields. All rules must match
       corresponding fields for the ruler to be valid.
    """
    extras = sorted([k for (k, v) in t.iteritems() if (
                     v and not k.isdigit())])
    set_completer(extras)
    guru_ruler = {}
    extras = {}
    field = True
    while field:
        # Enter field
        while True:
            # Update fields match indicators
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            field = quick_input('\nMatch on field', vanish=True).lower()
            regex = '*' in field
            field = field.strip('*')
            if not field or field in set(FIELDS_FULL.values()) - {'category'}:
                break
        # Enter match
        while field:
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            existing_match = guru_ruler.get(field, '')
            ruler = quick_input('\n%s match (%s)%s' % (field.title(),
                    'regex' if regex else 'chars',
                    ' [%s]' % existing_match if existing_match else ''),
                vanish=True)
            if ruler.isspace():  # remove field rule from ruler
                extras.pop(field, None)
                guru_ruler.pop(field, None)
                # break
            elif ruler:
                guru_ruler[field] = r'%s' % ruler if regex else re.escape(
                    ruler)
            match, extras = check_ruler(guru_ruler, t)
            if match:
                break
    return guru_ruler
Beispiel #16
0
def query_guru_ruler(t):
    """Define rules on a combination of fields. All rules must match
       corresponding fields for the ruler to be valid.
    """
    extras = sorted([k for (k, v) in t.items() if (v and not k.isdigit())])
    set_completer(extras)
    guru_ruler = {}
    extras = {}
    field = True
    while field:
        # Enter field
        while True:
            # Update fields match indicators
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            field = quick_input('\nMatch on field', vanish=True).lower()
            regex = '*' in field
            field = field.strip('*')
            if not field or field in set(
                    config.FIELDS_FULL.values()) - {'category'}:
                break
        # Enter match
        while field:
            print(TERM.move_y(0))
            print_transaction(t, short=False, extras=extras)
            existing_match = guru_ruler.get(field, '')
            ruler = quick_input(
                '\n%s match (%s)%s' %
                (field.title(), 'regex' if regex else 'chars',
                 ' [%s]' % existing_match if existing_match else ''),
                vanish=True)
            if ruler.isspace():  # remove field rule from ruler
                extras.pop(field, None)
                guru_ruler.pop(field, None)
            elif ruler:
                guru_ruler[field] = r'%s' % ruler if regex else re.escape(
                    ruler)
            match, extras = check_ruler(guru_ruler, t)
            if match:
                break
    return guru_ruler