1 |
# Common |
2 |
# |
3 |
# Douglas Thrift |
4 |
# |
5 |
# $Id$ |
6 |
|
7 |
import base64 |
8 |
from ConfigParser import SafeConfigParser |
9 |
import optparse |
10 |
import os.path |
11 |
import sys |
12 |
|
13 |
FORBIDDEN = ('common', 'creditcard', 'google', 'wesabe') |
14 |
|
15 |
class Bank(object): |
16 |
def download(self, account): |
17 |
raise NotImplementedError |
18 |
|
19 |
def due(self, account): |
20 |
raise NotImplementedError |
21 |
|
22 |
class OptionParser(optparse.OptionParser): |
23 |
def __init__(self, *args, **kwargs): |
24 |
optparse.OptionParser.__init__(self, *args, **kwargs) |
25 |
self.add_option('-A', '--all', action = 'store_true', dest = 'all') |
26 |
self.add_option('-b', '--bank', action = 'callback', callback = self.__bank, dest = 'banks', type = 'string') |
27 |
self.add_option('-a', '--account', action = 'callback', callback = self.__account, dest = 'banks', type = 'string') |
28 |
self.add_option('-l', '--list', action = 'store_true', dest = 'list') |
29 |
self.add_option('-D', '--debug', action = 'store_true', dest = 'debug') |
30 |
|
31 |
def __bank(self, option, opt_str, value, parser): |
32 |
if value in FORBIDDEN: |
33 |
raise optparse.OptionValueError, '%s must not be %s' % (opt_str, value) |
34 |
|
35 |
self.bank = value |
36 |
|
37 |
parser.values.ensure_value(option.dest, {}).setdefault(value, []) |
38 |
|
39 |
def __account(self, option, opt_str, value, parser): |
40 |
try: |
41 |
getattr(parser.values, option.dest)[self.bank].append(value) |
42 |
except NameError: |
43 |
raise optparse.OptionValueError, '%s must be after -b/--bank' % opt_str |
44 |
|
45 |
def config(parser, options, file): |
46 |
if not options.all and not options.banks and not options.list: |
47 |
parser.error('-A, -b, or -l not specified') |
48 |
|
49 |
config = SafeConfigParser() |
50 |
|
51 |
config.read([os.path.expanduser('~/%s' % file)]) |
52 |
|
53 |
banks = dict(map(lambda bank: (bank, config.get(bank, 'accounts').split(',')), (options.banks.iterkeys() if options.banks else filter(lambda section: section not in FORBIDDEN, config.sections())))) |
54 |
|
55 |
if options.banks: |
56 |
for bank in banks.iterkeys(): |
57 |
accounts = frozenset(options.banks[bank]) |
58 |
|
59 |
if accounts: |
60 |
all_accounts = frozenset(banks[bank]) |
61 |
|
62 |
if accounts <= all_accounts: |
63 |
banks[bank] = accounts |
64 |
else: |
65 |
parser.error('not account(s): %s' % ', '.join(accounts - all_accounts)) |
66 |
|
67 |
if options.list: |
68 |
for bank, accounts in banks.iteritems(): |
69 |
print bank |
70 |
|
71 |
for account in accounts: |
72 |
print ' ' + account |
73 |
|
74 |
sys.exit(0) |
75 |
|
76 |
return config, banks |
77 |
|
78 |
def decode(string): |
79 |
return base64.b64decode(string.decode('rot13')) |
80 |
|
81 |
def bank(bank, options, config): |
82 |
exec 'import %s' % bank |
83 |
exec "bank = %s.Bank(config.get(bank, 'username'), decode(config.get(bank, 'password')), options.debug)" % bank |
84 |
|
85 |
return bank |