]> jfr.im git - irc/rizon/acid.git/blame - pyva/src/main/python/pseudoclient/collection.py
Import acidictive 4 and pyva plugin
[irc/rizon/acid.git] / pyva / src / main / python / pseudoclient / collection.py
CommitLineData
685e346e
A
1from datetime import datetime\r
2from utils import *\r
3from istring import *\r
4import traceback\r
5import inspect\r
6\r
7class InvariantCollection(object):\r
8 def __init__(self):\r
9 self.__entries = {}\r
10\r
11 def __len__(self):\r
12 return len(self.__entries)\r
13\r
14 def __getitem__(self, key):\r
15 invariant_key = istring(key)\r
16\r
17 if not self.__contains__(invariant_key):\r
18 raise KeyError('Entry with key %s not present.' % key)\r
19\r
20 return self.__entries[invariant_key]\r
21\r
22 def __setitem__(self, key, value):\r
23 self.__entries[istring(key)] = value\r
24\r
25 def __delitem__(self, key):\r
26 invariant_key = istring(key)\r
27\r
28 if not self.__contains__(invariant_key):\r
29 raise KeyError('Entry with key %s not present.' % key)\r
30\r
31 del(self.__entries[invariant_key])\r
32\r
33 def __iter__(self):\r
34 for entry in self.__entries:\r
35 yield entry\r
36\r
37 def __contains__(self, item):\r
38 if not isinstance(item, basestring):\r
39 raise TypeError('%s is not an allowed indexing type.' % type(item))\r
40\r
41 return istring(item) in self.__entries\r
42 \r
43 def list_all(self):\r
44 return [self[item] for item in self]\r
45\r
46class CollectionEntity(object):\r
47 def __init__(self, id, ban_source = None, ban_reason = None, ban_date = None, ban_expiry = None):\r
48 self.id = id\r
49 self.ban_source = ban_source\r
50 self.ban_reason = ban_reason\r
51 self.ban_date = ban_date\r
52 self.ban_expiry = ban_expiry\r
53 self.dirty = False\r
54 self.registered = self.banned = False\r
55\r
56class CollectionManager(InvariantCollection):\r
57 def __init__(self, type):\r
58 InvariantCollection.__init__(self)\r
59 self.__type = type\r
60 self.__deleted_items = []\r
61\r
62 self.db_open()\r
63\r
64 self.load()\r
65\r
66 def load(self):\r
67 self.cursor.execute("CREATE TABLE IF NOT EXISTS " + self.module.name + "_" + self.name + " (id INT NOT NULL AUTO_INCREMENT, name VARCHAR(51) NOT NULL, PRIMARY KEY (id), UNIQUE KEY (name)) ENGINE=InnoDB")\r
68\r
69 self.cursor.execute("CREATE TABLE IF NOT EXISTS " + self.module.name + "_" + self.name + "_options (id INT, name VARCHAR(32) NOT NULL, value TINYTEXT, UNIQUE KEY (id, name)) ENGINE=InnoDB")\r
70 #self.cursor.execute("ALTER TABLE " + self.module.name + "_" + self.name + "_options ADD CONSTRAINT FOREIGN KEY IF NOT EXISTS (id) REFERENCES " + self.module.name + "_" + self.name + " (id)")\r
71\r
72 self.cursor.execute("SELECT id, name FROM " + self.module.name + "_" + self.name)\r
73 r = self.cursor.fetchall()\r
74\r
75 for row in r:\r
76 id = row[0]\r
77 name = istring(row[1])\r
78\r
79 self.module.elog.debug('Loading ' + name + ' for ' + self.module.name + '_' + self.name)\r
80\r
81 self[name] = e = self.__type(id, name)\r
82\r
83 self.cursor.execute("SELECT name,value FROM " + self.module.name + "_" + self.name + "_options WHERE `id` = %s", (id,))\r
84 r2 = self.cursor.fetchall()\r
85 for row2 in r2:\r
86 setattr(e, row2[0], row2[1])\r
87\r
88 def __get_attributes(self, obj):\r
89 boring = dir(type('dummy', (object,), {}))\r
90 return [item for item in inspect.getmembers(obj) if item[0] not in boring]\r
91\r
92 def commit(self):\r
93 try:\r
94 deleted = [(e.id, ) for e in self.list_deleted()]\r
95 changed = [e for e in self.list_dirty()]\r
96\r
97 if len(deleted) > 0:\r
98 self.cursor.executemany("DELETE FROM " + self.module.name + "_" + self.name + "_options WHERE id = %s", deleted)\r
99 self.cursor.executemany("DELETE FROM " + self.module.name + "_" + self.name + " WHERE id = %s", deleted)\r
100 self.module.elog.commit('Deleted %d %s from database.' % (len(deleted), self.name))\r
101\r
102 for e in changed:\r
103 if e.id == -1:\r
104 self.cursor.execute("INSERT INTO " + self.module.name + "_" + self.name + " (name) VALUES(%s)", (e.name,))\r
105 e.id = self.cursor.lastrowid\r
106 else: # delete options as we are aboue to re-flush them\r
107 self.cursor.execute("DELETE FROM " + self.module.name + "_" + self.name + "_options WHERE `id` = %s", (e.id,))\r
108\r
109 for a in self.__get_attributes(e):\r
110 attr_name = a[0]\r
111 attr = getattr(e, attr_name)\r
112 if attr:\r
113 self.cursor.execute("INSERT INTO " + self.module.name + "_" + self.name + "_options (id, name, value) VALUES (%s, %s, %s)", (e.id, attr_name, attr))\r
114 if len(changed) > 0:\r
115 self.module.elog.commit('Committed %d %s to database.' % (len(changed), self.name))\r
116\r
117 self.clear_deleted()\r
118\r
119 for e in self.list_all():\r
120 e.dirty = False\r
121 except Exception, err:\r
122 traceback.print_exc()\r
123 self.module.elog.error(self.name + ' commit failed: @b%s@b' % err)\r
124\r
125 def check(self, item):\r
126 if not item in self:\r
127 return\r
128\r
129 entity = self[item]\r
130\r
131 if entity.ban_expiry != None and entity.ban_expiry <= unix_time(datetime.now()):\r
132 self.unban(item)\r
133\r
134 def is_dirty(self, item):\r
135 self.check(item)\r
136\r
137 return item in self and self[item].dirty\r
138\r
139 def is_valid(self, item):\r
140 self.check(item)\r
141\r
142 return item in self and self[item].registered and not self[item].banned\r
143\r
144 def is_banned(self, item):\r
145 self.check(item)\r
146\r
147 return item in self and self[item].banned\r
148\r
149 def get(self, item, attribute):\r
150 if not item in self:\r
151 return None\r
152\r
153 return getattr(self[item], attribute)\r
154\r
155 def set(self, item, attribute, value):\r
156 entity = self.add(item)\r
157 old_value = getattr(entity, attribute)\r
158\r
159 if old_value != value:\r
160 setattr(entity, attribute, value)\r
161 entity.dirty = True\r
162\r
163 def add(self, item):\r
164 if not item in self:\r
165 entity = self.__type(-1, item)\r
166 entity.dirty = True\r
167 entity.registered = True\r
168 self[item] = entity\r
169\r
170 self.on_added(item)\r
171\r
172 return self[item]\r
173\r
174 def remove(self, item):\r
175 if not item in self:\r
176 return\r
177\r
178 entity = self[item]\r
179\r
180 if entity.banned and entity.registered:\r
181 entity.registered = False\r
182 entity.clear()\r
183 entity.dirty = True\r
184 elif not entity.banned:\r
185 if not item.lower() in self.__deleted_items:\r
186 self.__deleted_items.append(entity)\r
187\r
188 del(self[item])\r
189\r
190 self.on_removed(item)\r
191\r
192 def ban(self, item, source, reason, date, expiry):\r
193 entity = self.add(item)\r
194 entity.banned = True\r
195 entity.ban_source = source\r
196 entity.ban_reason = reason\r
197 entity.ban_date = date\r
198 entity.ban_expiry = expiry\r
199 entity.dirty = True\r
200\r
201 self.on_banned(item)\r
202\r
203 def unban(self, item):\r
204 if not item in self or not self[item].banned:\r
205 return\r
206\r
207 entity = self[item]\r
208 entity.banned = False\r
209 entity.ban_source = None\r
210 entity.ban_reason = None\r
211 entity.ban_date = None\r
212 entity.ban_expiry = None\r
213\r
214 if not entity.registered:\r
215 self.remove(item)\r
216 else:\r
217 entity.dirty = True\r
218\r
219 self.on_unbanned(item)\r
220\r
221 def on_added(self, item):\r
222 pass\r
223\r
224 def on_removed(self, item):\r
225 pass\r
226\r
227 def on_banned(self, item):\r
228 pass\r
229\r
230 def on_unbanned(self, item):\r
231 pass\r
232\r
233 def clear_deleted(self):\r
234 self.__deleted_items = []\r
235\r
236 def list_deleted(self):\r
237 return self.__deleted_items\r
238\r
239 def list_dirty(self):\r
240 items = [item for item in self]\r
241 return [self[item] for item in items if self.is_dirty(item)]\r
242\r
243 def list_valid(self):\r
244 items = [item for item in self]\r
245 return [self[item] for item in items if self.is_valid(item)]\r
246\r
247 def list_banned(self):\r
248 items = [item for item in self]\r
249 return [self[item] for item in items if self.is_banned(item)]\r