Added some convenient __all__ imports.
[didex.git] / didex / values.py
CommitLineData
b080a59c
FT
1import threading
2from . import store, lib
3from .store import storedesc
4
cbf73d3a
FT
5__all__ = ["simple", "multi"]
6
b080a59c
FT
7class cursor(lib.closable):
8 def __init__(self, bk, st):
9 self.bk = bk
10 self.st = st
11
12 def close(self):
13 self.bk.close()
14
15 def __iter__(self):
16 return self
17
18 def __next__(self):
19 k, id = next(self.bk)
20 return k, self.st.get(id)
21
22 def skip(self, n=1):
23 self.bk.skip(n)
24
25class base(storedesc):
26 def __init__(self, store, indextype, name, datatype, default):
27 self.store = store
28 self.indextype = indextype
29 self.name = name
30 self.typ = datatype
31 self.default = default
32 self.idx = None
33 self.lk = threading.Lock()
34 self.mattr = "__idx_%s_new" % name
35 self.iattr = "__idx_%s_cur" % name
36
37 def index(self):
38 with self.lk:
39 if self.idx is None:
40 self.idx = self.indextype(self.store.db(), self.name, self.typ)
41 return self.idx
42
43 def __get__(self, obj, cls):
44 if obj is None: return self
45 return getattr(obj, self.mattr, self.default)
46
47 def __set__(self, obj, val):
48 setattr(obj, self.mattr, val)
49
50 def __delete__(self, obj):
51 delattr(obj, self.mattr)
52
53 def get(self, **kwargs):
54 return cursor(self.index().get(**kwargs), self.store)
55
56class simple(base):
57 def __init__(self, store, indextype, name, datatype, default=None):
58 super().__init__(store, indextype, name, datatype, default)
59
60 def register(self, id, obj, tx):
61 val = self.__get__(obj, None)
62 self.index().put(val, id, tx=tx)
63 tx.postcommit(lambda: setattr(obj, self.iattr, val))
64
65 def unregister(self, id, obj, tx):
66 self.index().remove(getattr(obj, self.iattr), id, tx=tx)
67 tx.postcommit(lambda: delattr(obj, self.iattr))
68
69 def update(self, id, obj, tx):
70 val = self.__get__(obj, None)
71 ival = getattr(obj, self.iattr)
72 if val != ival:
73 idx = self.index()
74 idx.remove(ival, id, tx=tx)
75 idx.put(val, id, tx=tx)
76 tx.postcommit(lambda: setattr(obj, self.iattr, val))
77
78class multi(base):
79 def __init__(self, store, indextype, name, datatype):
80 super().__init__(store, indextype, name, datatype, ())
81
82 def register(self, id, obj, tx):
83 vals = frozenset(self.__get__(obj, None))
84 idx = self.index()
85 for val in vals:
86 idx.put(val, id, tx=tx)
87 tx.postcommit(lambda: setattr(obj, self.iattr, vals))
88
89 def unregister(self, id, obj, tx):
90 idx = self.index()
91 for val in getattr(obj, self.iattr):
92 idx.remove(val, id, tx=tx)
93 tx.postcommit(lambda: delattr(obj, self.iattr))
94
95 def update(self, id, obj, tx):
96 vals = frozenset(self.__get__(obj, None))
97 ivals = getattr(obj, self.iattr)
98 if vals != ivals:
99 idx = self.index()
100 for val in ivals - vals:
101 idx.remove(val, id, tx=tx)
102 for val in vals - ivals:
103 idx.put(val, id, tx=tx)
104 tx.postcommit(lambda: setattr(obj, self.iattr, vals))