netbank: Changed login syntax.
[fulbank.git] / fulbank / data.py
1 import os, pwd, hashlib, pickle
2
3 def _localname(type):
4     mod = type.__module__
5     if mod.startswith("fulbank."):
6         mod = mod[8:]
7     return "%s.%s" % (mod, type.__name__)
8
9 class account(object):
10     @property
11     def number(self): raise NotImplementedError("account.number")
12     @property
13     def name(self): raise NotImplementedError("account.name")
14     def transactions(self): raise NotImplementedError("account.transactions")
15
16     def __repr__(self):
17         return "#<%s %s: %r>" % (_localname(type(self)), self.number, self.name)
18
19 class txnaccount(account):
20     @property
21     def balance(self): raise NotImplementedError("txnaccount.balance")
22     @property
23     def clearing(self): raise NotImplementedError("txnaccount.clearing")
24     @property
25     def fullnumber(self): raise NotImplementedError("txnaccount.fullnumber")
26
27 class cardaccount(account):
28     pass
29
30 class transaction(object):
31     @property
32     def value(self): raise NotImplementedError("transaction.value")
33     @property
34     def message(self): raise NotImplementedError("transaction.message")
35     @property
36     def date(self): raise NotImplementedError("transaction.date")
37
38     @property
39     def hash(self):
40         dig = hashlib.sha256()
41         dig.update(str(self.date.toordinal()).encode("ascii") + b"\0")
42         dig.update(self.message.encode("utf-8") + b"\0")
43         dig.update(str(self.value.amount).encode("ascii") + b"\0")
44         dig.update(self.value.currency.symbol.encode("ascii") + b"\0")
45         return dig.hexdigest()
46
47     def __repr__(self):
48         return "#<%s %s: %r>" % (_localname(type(self)), self.value, self.message)
49
50 class session(object):
51     def save(self, filename):
52         with open(filename, "wb") as fp:
53             pickle.dump(self, fp)
54
55     @staticmethod
56     def load(filename):
57         with open(filename, "rb") as fp:
58             return pickle.load(fp)
59
60 def getsessnam(name):
61     if name == "fsb":
62         from . import fsb
63         return fsb.session
64     raise ValueError("no such known session type: " + name)
65
66 def _sesspath(name):
67     return os.path.join(pwd.getpwuid(os.getuid()).pw_dir, ".cache/fulbank", name)
68
69 def defaultsess():
70     ret = os.getenv("NETBANKSESS")
71     if ret:
72         return ret
73     return "master"
74
75 def loadsess(name=None, default=FileNotFoundError):
76     if name is None: name = defaultsess()
77     path = _sesspath(name)
78     if not os.path.exists(path):
79         if default is FileNotFoundError:
80             raise FileNotFoundError(name)
81         return default
82     return session.load(path)
83
84 def savesess(sess, name=None):
85     if name is None: name = defaultsess()
86     path = _sesspath(name)
87     if sess is not None:
88         sessdir = os.path.dirname(path)
89         if not os.path.isdir(sessdir):
90             os.makedirs(sessdir)
91         return sess.save(_sesspath(name))
92     else:
93         if os.path.exists(path):
94             os.unlink(path)
95
96 class savedsess(object):
97     def __init__(self, name=None):
98         if name is None: name = defaultsess()
99         self.name = name
100         self.sess = None
101
102     def __enter__(self):
103         self.sess = loadsess(self.name)
104         return self.sess
105
106     def __exit__(self):
107         savesess(self.sess, name)
108         self.sess = None