def test_eval_expr(self): self.assertEqual(-100, util.eval_expr("-100")) self.assertEqual(4, util.eval_expr("2^6")) self.assertEqual(64, util.eval_expr("2**6")) self.assertEqual(-5, util.eval_expr("1 + 2*3**(4^5) / (6 + -7)")) self.assertEqual(12.873000000000001, util.eval_expr("12*1.07275")) self.assertEqual(-2, util.eval_expr("~1")) # invert with self.assertRaises(TypeError): util.eval_expr("a")
def _jf_verify_value(parts): # function to get groups of tags easily gtgs = lambda *x: [job_file_tags[a] for a in x] # handle blank values if not parts[1]: # ok only if tag allows blanks if parts[0] in jft_blank_ok: return True return False # handle files if parts[0] in jft_files: if not parts[1]: pass return os.path.isfile(parts[1]) # directories if parts[0] in jft_dirs: if not parts[1]: pass # try to create if doesn't exist if not os.path.isdir(parts[1]): try: os.makedirs(parts[1]) except: return False # the directory exists now, if it didn't before return True # handle numbers # expression-allowing if parts[0] in jft_exprs: if not parts[1]: pass parts[1] = ut.eval_expr(parts[1]) if parts[1] is None: return False return True # non-expression allowing if parts[0] in jft_nums: if not parts[1]: pass try: parts[1] = int(parts[1]) except: return False return True # multiple/restricted choice if parts[0] in jft_mch: return _check_mch_tags(parts) # should never get here return False
def _parse_transaction_lines(self, lines): if not self.rec_account or not lines: # currently only care about transaction lines if reconciling return # - most likely only one line for the account we're reconciling, # but we'll have to handle more than one # - we only care about total for the account, but we need to # total everything up in case our account doesn't have a # dollar amount and we need to calculate it transaction_total = 0 account_total = 0 need_math = False previous_status = None for line in lines: m = re.match(self.ENTRY_REGEX, line) if not m: continue status, account, amount = m.groups() if amount is not None: amount = amount.strip() if amount == '': amount = None else: amount = util.eval_expr( re.sub(r'[$,]', '', amount) ) transaction_total += amount if self.rec_account not in account: continue if account.strip() not in self.rec_account_matches: self.rec_account_matches.append(account.strip()) status = status if status else '' if previous_status is None: self.rec_status = status previous_status = status else: if previous_status != status \ and len(self.rec_account_matches) < 2: # not going to raise this if multiple account # matches since it's blowing up anyway, and maybe # multiple statuses because of multiple accounts raise LdgReconcilerMultipleStatuses( REC_STATUS_ERROR_MESSAGE.format( date=self.get_date_string(), payee=self.payee ) ) if amount is None: need_math = True else: account_total += amount if len(self.rec_account_matches) > 1: raise LdgReconcilerMoreThanOneMatchingAccount( self.rec_account_matches ) if len(self.rec_account_matches) > 0: if need_math: # transaction_total should be 0; use it to adjust account_total -= transaction_total transaction_total -= transaction_total assert transaction_total == 0 self.rec_amount = account_total