def diff(_str, candidate, term, as_error=False): """ Return a string representing how well candidate matches str : matching words are green, partial matches (chars) are orange. If as_error is True, non matching chars are red. """ match = SequenceMatcher(None, _str.lower(), candidate.lower()) match_indexes = match.find_longest_match(0, len(_str), 0, len(candidate)) _, beg, end = match_indexes match = candidate[beg:beg + end] words = match.split(' ') res = term.red(candidate[:beg]) if as_error else candidate[:beg] for w in words: res += (term.green(w) if tags.is_match(w, _str) else term.yellow(w)) + ' ' res += '\b' + (term.red(candidate[beg + end:]) if as_error else candidate[beg + end:]) return res
def query_match(payee): """Query a match for payee line as long as a correct one is not entered. """ set_completer(sorted(complete_matches(payee))) while True: match = quick_input('Match') if match.isspace(): # Go back, discard entered category print(2 * CLEAR, end='') break if not tags.is_match(match, payee): print(CLEAR + '%s Match rejected: %s' % (TERM.red('✖'), diff(payee, match, TERM, as_error=True))) else: print(CLEAR + "%s Match accepted: %s" % (TERM.green('✔'), str(match) if match else TERM.red('<none>'))) break set_completer() return match
def query_match(payee): """Query a match for payee line as long as a correct one is not entered. """ set_completer(sorted(complete_matches(payee))) while True: match = quick_input('Match') if match.isspace(): # Go back, discard entered category print(2 * CLEAR, end='') break if not tags.is_match(match, payee): print(CLEAR + '%s Match rejected: %s' % (TERM.red('✖'), diff(payee, match, TERM, as_error=True))) else: print( CLEAR + "%s Match accepted: %s" % (TERM.green('✔'), str(match) if match else TERM.red('<none>'))) break set_completer() return match
def test_is_match(self): self.assertTrue(tags.is_match('sully bar', self.transaction[0]['payee']))