... | ... |
@@ -8,18 +8,7 @@ import time |
8 | 8 |
import argparse |
9 | 9 |
from prettytable import PrettyTable |
10 | 10 |
from termcolor import colored |
11 |
- |
|
12 |
-UNUSUAL_BALANCE_THRESHOLD = 500.0 |
|
13 |
-WORRYING_BALANCE_THRESHOLD = 100.0 |
|
14 |
-HOLYSHIT_BALANCE_THRESHOLD = 0 |
|
15 |
-MAX_AGE = 24 * 60 * 60 |
|
16 |
- |
|
17 |
-CURRENCIES = { |
|
18 |
- 'EUR': '€', |
|
19 |
- 'USD': '$', |
|
20 |
- 'GBP': '£', |
|
21 |
- 'YEN': '¥' |
|
22 |
-} |
|
11 |
+from boobank_utils import * |
|
23 | 12 |
|
24 | 13 |
def parse_args(): |
25 | 14 |
args_parser = argparse.ArgumentParser(description='Display the contents of cached "boobank list" JSON files.') |
... | ... |
@@ -41,7 +30,7 @@ def main(): |
41 | 30 |
print(table) |
42 | 31 |
total_line = '%-60s' % '' |
43 | 32 |
total_line += colored('Total: ', 'white', attrs=['bold']) |
44 |
- total_line += format_balance({'balance': total}) |
|
33 |
+ total_line += format_amount(total, DEFAULT_CURRENCY, COLORING_THRESHOLD) |
|
45 | 34 |
print(total_line) |
46 | 35 |
|
47 | 36 |
def get_accounts(accounts_json_path): |
... | ... |
@@ -63,34 +52,10 @@ def get_table(): |
63 | 52 |
def add_account(table, account, cache_timestamp): |
64 | 53 |
id = colored(account.get('id'), 'cyan') |
65 | 54 |
label = colored(account.get('label'), 'cyan') |
66 |
- balance = format_balance(account) |
|
55 |
+ currency = account.get('currency', DEFAULT_CURRENCY) |
|
56 |
+ balance = format_amount(account['balance'], currency, COLORING_THRESHOLD) |
|
67 | 57 |
cache_date = format_timestamp_colored(cache_timestamp, MAX_AGE) |
68 | 58 |
table.add_row([id, label, balance, cache_date]) |
69 | 59 |
|
70 |
-def format_balance(account): |
|
71 |
- balance = account.get('balance') |
|
72 |
- currency = account.get('currency', 'EUR') |
|
73 |
- balance_format = '%12.2f ' |
|
74 |
- balance_format += CURRENCIES.get(currency, currency) |
|
75 |
- |
|
76 |
- balance_color = 'green' |
|
77 |
- balance_attr = [] |
|
78 |
- if balance < HOLYSHIT_BALANCE_THRESHOLD: |
|
79 |
- balance_color = 'red' |
|
80 |
- balance_attr = ['blink'] |
|
81 |
- elif balance < WORRYING_BALANCE_THRESHOLD: |
|
82 |
- balance_color = 'red' |
|
83 |
- elif balance < UNUSUAL_BALANCE_THRESHOLD: |
|
84 |
- balance_color = 'yellow' |
|
85 |
- return colored(balance_format % balance, balance_color, attrs=balance_attr) |
|
86 |
- |
|
87 |
-def format_timestamp_colored(timestamp, max_age): |
|
88 |
- result = format_timestamp(timestamp) |
|
89 |
- color = 'red' if timestamp + max_age < time.time() else 'green' |
|
90 |
- return colored(result, color) |
|
91 |
- |
|
92 |
-def format_timestamp(timestamp): |
|
93 |
- return time.strftime('%A %Y-%m-%d %H:%M:%S %Z', time.localtime(timestamp)) |
|
94 |
- |
|
95 | 60 |
if __name__ == '__main__': |
96 | 61 |
main() |
... | ... |
@@ -10,23 +10,13 @@ import time |
10 | 10 |
import errno |
11 | 11 |
import argparse |
12 | 12 |
import subprocess |
13 |
- |
|
14 |
-DEFAULT_CONF_FILE = '~/.config/boobank-cacher/conf.json' |
|
13 |
+from boobank_utils import * |
|
15 | 14 |
|
16 | 15 |
def get_conf(conf_path): |
17 | 16 |
conf_path = os.path.expanduser(conf_path) |
18 | 17 |
with open(conf_path, 'r') as filedesc: |
19 | 18 |
return json.load(filedesc) |
20 | 19 |
|
21 |
-def mkdir(path, mode): |
|
22 |
- try: |
|
23 |
- os.makedirs(path, mode) |
|
24 |
- except OSError as exc: |
|
25 |
- if exc.errno == errno.EEXIST and os.path.isdir(path): |
|
26 |
- pass |
|
27 |
- else: |
|
28 |
- raise |
|
29 |
- |
|
30 | 20 |
def run_boobank(conf): |
31 | 21 |
results = copy.deepcopy(conf) |
32 | 22 |
# Ensure there is at least one command to run: |
... | ... |
@@ -8,15 +8,7 @@ import time |
8 | 8 |
import argparse |
9 | 9 |
from prettytable import PrettyTable |
10 | 10 |
from termcolor import colored |
11 |
- |
|
12 |
-MAX_AGE = 24 * 60 * 60 |
|
13 |
- |
|
14 |
-CURRENCIES = { |
|
15 |
- 'EUR': '€', |
|
16 |
- 'USD': '$', |
|
17 |
- 'GBP': '£', |
|
18 |
- 'YEN': '¥' |
|
19 |
-} |
|
11 |
+from boobank_utils import * |
|
20 | 12 |
|
21 | 13 |
def parse_args(): |
22 | 14 |
args_parser = argparse.ArgumentParser(description='Display the contents of a cached "boobank history" JSON file.') |
... | ... |
@@ -60,26 +52,9 @@ def get_table(timestamp): |
60 | 52 |
def add_operation(table, operation): |
61 | 53 |
date = colored(operation.get('date'), 'cyan') |
62 | 54 |
label = colored(operation.get('label')[:80], 'cyan') |
63 |
- amount = format_amount(operation) |
|
55 |
+ currency = operation.get('currency', DEFAULT_CURRENCY) |
|
56 |
+ amount = format_amount(operation['amount'], currency, COLORING_SIMPLE) |
|
64 | 57 |
table.add_row([date, label, amount]) |
65 | 58 |
|
66 |
-def format_amount(account): |
|
67 |
- amount = account.get('amount') |
|
68 |
- currency = account.get('currency', 'EUR') |
|
69 |
- amount_format = '%12.2f ' |
|
70 |
- amount_format += CURRENCIES.get(currency, currency) |
|
71 |
- |
|
72 |
- amount_color = 'green' if amount >= 0 else 'red' |
|
73 |
- amount_attr = [] |
|
74 |
- return colored(amount_format % amount, amount_color, attrs=amount_attr) |
|
75 |
- |
|
76 |
-def format_timestamp_colored(timestamp, max_age): |
|
77 |
- result = format_timestamp(timestamp) |
|
78 |
- color = 'red' if timestamp + max_age < time.time() else 'green' |
|
79 |
- return colored(result, color) |
|
80 |
- |
|
81 |
-def format_timestamp(timestamp): |
|
82 |
- return time.strftime('%A %Y-%m-%d %H:%M:%S %Z', time.localtime(timestamp)) |
|
83 |
- |
|
84 | 59 |
if __name__ == '__main__': |
85 | 60 |
main() |
86 | 61 |
new file mode 100644 |
... | ... |
@@ -0,0 +1,84 @@ |
1 |
+# -*- coding: utf-8 -*- |
|
2 |
+""" |
|
3 |
+This module provides various functions and constants used by the boobank-utils |
|
4 |
+tools. |
|
5 |
+""" |
|
6 |
+import os |
|
7 |
+import time |
|
8 |
+import errno |
|
9 |
+from termcolor import colored |
|
10 |
+ |
|
11 |
+DEFAULT_CONF_FILE = '~/.config/boobank-cacher/conf.json' |
|
12 |
+MAX_AGE = 24 * 60 * 60 |
|
13 |
+ |
|
14 |
+UNUSUAL_THRESHOLD = 500.0 |
|
15 |
+WORRYING_THRESHOLD = 100.0 |
|
16 |
+HOLYSHIT_THRESHOLD = 0 |
|
17 |
+ |
|
18 |
+CURRENCIES = { |
|
19 |
+ 'EUR': '€', |
|
20 |
+ 'USD': '$', |
|
21 |
+ 'GBP': '£', |
|
22 |
+ 'YEN': '¥' |
|
23 |
+} |
|
24 |
+DEFAULT_CURRENCY = 'EUR' |
|
25 |
+ |
|
26 |
+COLORING_NONE = 0 |
|
27 |
+COLORING_SIMPLE = 1 |
|
28 |
+COLORING_THRESHOLD = 2 |
|
29 |
+COLORING_MAX = 3 |
|
30 |
+ |
|
31 |
+def format_timestamp_colored(timestamp, max_age): |
|
32 |
+ """ |
|
33 |
+ Format the given Unix timestamp for puny humans. |
|
34 |
+ Additionally, the timestamp is colored: red if older than max_age, false |
|
35 |
+ otherwise. This is useful to show whether cached data are obsolete. |
|
36 |
+ """ |
|
37 |
+ result = format_timestamp(timestamp) |
|
38 |
+ color = 'red' if timestamp + max_age < time.time() else 'green' |
|
39 |
+ return colored(result, color) |
|
40 |
+ |
|
41 |
+def format_timestamp(timestamp): |
|
42 |
+ """ |
|
43 |
+ Format the given Unix timestamp for puny humans. |
|
44 |
+ """ |
|
45 |
+ return time.strftime('%A %Y-%m-%d %H:%M:%S %Z', time.localtime(timestamp)) |
|
46 |
+ |
|
47 |
+def format_amount(amount, currency=DEFAULT_CURRENCY, coloring=None): |
|
48 |
+ """ |
|
49 |
+ Format the given amount and currency into an optionally colored string. |
|
50 |
+ """ |
|
51 |
+ amount_format = '%12.2f ' + CURRENCIES.get(currency, currency) |
|
52 |
+ result = amount_format % amount |
|
53 |
+ |
|
54 |
+ if coloring < COLORING_SIMPLE or coloring >= COLORING_MAX: |
|
55 |
+ return result |
|
56 |
+ |
|
57 |
+ amount_color = 'green' |
|
58 |
+ amount_attr = [] |
|
59 |
+ if coloring == COLORING_SIMPLE: |
|
60 |
+ if amount < 0: |
|
61 |
+ amount_color = 'red' |
|
62 |
+ else: |
|
63 |
+ # Assume COLORING_THRESHOLD: |
|
64 |
+ if amount < HOLYSHIT_THRESHOLD: |
|
65 |
+ amount_color = 'red' |
|
66 |
+ amount_attr = ['blink'] |
|
67 |
+ elif amount < WORRYING_THRESHOLD: |
|
68 |
+ amount_color = 'red' |
|
69 |
+ elif amount < UNUSUAL_THRESHOLD: |
|
70 |
+ amount_color = 'yellow' |
|
71 |
+ return colored(result, amount_color, attrs=amount_attr) |
|
72 |
+ |
|
73 |
+def mkdir(path, mode): |
|
74 |
+ """ |
|
75 |
+ Create a directory along with all missing parents. |
|
76 |
+ All created directories get assigned the given Unix mode. |
|
77 |
+ """ |
|
78 |
+ try: |
|
79 |
+ os.makedirs(path, mode) |
|
80 |
+ except OSError as exc: |
|
81 |
+ if exc.errno == errno.EEXIST and os.path.isdir(path): |
|
82 |
+ pass |
|
83 |
+ else: |
|
84 |
+ raise |