dwho 0.3.60__py2.py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- dwho/__init__.py +4 -0
- dwho/adapters/__init__.py +4 -0
- dwho/adapters/redis.py +289 -0
- dwho/classes/__init__.py +4 -0
- dwho/classes/abstract.py +237 -0
- dwho/classes/errors.py +16 -0
- dwho/classes/inoplugs.py +204 -0
- dwho/classes/inotify.py +621 -0
- dwho/classes/libloader.py +63 -0
- dwho/classes/modules.py +233 -0
- dwho/classes/notifiers.py +585 -0
- dwho/classes/objects.py +385 -0
- dwho/classes/plugins.py +100 -0
- dwho/config.py +294 -0
- dwho/helpers/__init__.py +4 -0
- dwho/helpers/crypto.py +139 -0
- dwho/modules/__init__.py +28 -0
- dwho/modules/web.py +24 -0
- dwho/plugins/__init__.py +28 -0
- dwho-0.3.60.dist-info/METADATA +200 -0
- dwho-0.3.60.dist-info/RECORD +24 -0
- dwho-0.3.60.dist-info/WHEEL +6 -0
- dwho-0.3.60.dist-info/licenses/LICENSE +674 -0
- dwho-0.3.60.dist-info/top_level.txt +1 -0
dwho/__init__.py
ADDED
dwho/adapters/redis.py
ADDED
|
@@ -0,0 +1,289 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2015-2019 Adrien Delle Cave
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
"""dwho.adapters.redis"""
|
|
5
|
+
|
|
6
|
+
from __future__ import absolute_import
|
|
7
|
+
|
|
8
|
+
from six import iteritems, iterkeys
|
|
9
|
+
from six.moves.urllib.parse import urlparse, parse_qs
|
|
10
|
+
|
|
11
|
+
from redis import Redis
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class DWhoAdapterRedis(object): # pylint: disable=useless-object-inheritance
|
|
15
|
+
def __init__(self, config, prefix = None, load = True):
|
|
16
|
+
self.config = config
|
|
17
|
+
self.servers = {}
|
|
18
|
+
|
|
19
|
+
if load:
|
|
20
|
+
self.load(prefix)
|
|
21
|
+
|
|
22
|
+
def load(self, prefix = None):
|
|
23
|
+
for name in iterkeys(self.config['general']['redis']):
|
|
24
|
+
if not prefix or name.startswith(prefix):
|
|
25
|
+
self.connect(name)
|
|
26
|
+
|
|
27
|
+
def connect(self, name):
|
|
28
|
+
if name not in self.servers:
|
|
29
|
+
self.servers[name] = {'conn': None, 'options': {}}
|
|
30
|
+
|
|
31
|
+
if self.servers[name]['conn']:
|
|
32
|
+
return self.servers[name]
|
|
33
|
+
|
|
34
|
+
has_from_url = hasattr(Redis, 'from_url')
|
|
35
|
+
for key, value in iteritems(self.config['general']['redis'][name]):
|
|
36
|
+
if key != 'url':
|
|
37
|
+
self.servers[name]['options'][key] = value
|
|
38
|
+
continue
|
|
39
|
+
elif has_from_url:
|
|
40
|
+
self.servers[name]['conn'] = Redis().from_url(value)
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
p = urlparse(value)
|
|
44
|
+
rconf = {'host': p.hostname,
|
|
45
|
+
'port': int(p.port or 6379),
|
|
46
|
+
'db': 0}
|
|
47
|
+
|
|
48
|
+
if p.query:
|
|
49
|
+
q = parse_qs(p.query)
|
|
50
|
+
if 'db' in q:
|
|
51
|
+
rconf['db'] = int(q['db'][0])
|
|
52
|
+
|
|
53
|
+
self.servers[name]['conn'] = Redis(**rconf)
|
|
54
|
+
|
|
55
|
+
return self.servers[name]
|
|
56
|
+
|
|
57
|
+
def ping(self, servers = None, prefix = None):
|
|
58
|
+
r = {}
|
|
59
|
+
|
|
60
|
+
if not servers:
|
|
61
|
+
servers = self.servers
|
|
62
|
+
|
|
63
|
+
for name, server in iteritems(servers):
|
|
64
|
+
if not prefix or name.startswith(prefix):
|
|
65
|
+
r[name] = server['conn'].ping()
|
|
66
|
+
|
|
67
|
+
return r
|
|
68
|
+
|
|
69
|
+
def set_key(self, key, val, expire = None, servers = None, prefix = None):
|
|
70
|
+
r = {}
|
|
71
|
+
|
|
72
|
+
if not servers:
|
|
73
|
+
servers = self.servers
|
|
74
|
+
|
|
75
|
+
if expire is not None:
|
|
76
|
+
for name, server in iteritems(servers):
|
|
77
|
+
if not prefix or name.startswith(prefix):
|
|
78
|
+
r[name] = server['conn'].setex(name = key, time = expire, value = val)
|
|
79
|
+
else:
|
|
80
|
+
for name, server in iteritems(servers):
|
|
81
|
+
if not prefix or name.startswith(prefix):
|
|
82
|
+
r[name] = server['conn'].set(key, val)
|
|
83
|
+
|
|
84
|
+
return r
|
|
85
|
+
|
|
86
|
+
def get_key(self, key, servers = None, prefix = None):
|
|
87
|
+
if not servers:
|
|
88
|
+
servers = self.servers
|
|
89
|
+
|
|
90
|
+
for name, server in iteritems(servers):
|
|
91
|
+
if (not prefix or name.startswith(prefix)) \
|
|
92
|
+
and server['conn'].exists(key):
|
|
93
|
+
return server['conn'].get(key)
|
|
94
|
+
|
|
95
|
+
return None
|
|
96
|
+
|
|
97
|
+
def del_key(self, key, servers = None, prefix = None):
|
|
98
|
+
r = {}
|
|
99
|
+
|
|
100
|
+
if not servers:
|
|
101
|
+
servers = self.servers
|
|
102
|
+
|
|
103
|
+
if not isinstance(key, (list, tuple)):
|
|
104
|
+
key = [key]
|
|
105
|
+
|
|
106
|
+
for name, server in iteritems(servers):
|
|
107
|
+
if not prefix or name.startswith(prefix):
|
|
108
|
+
r[name] = server['conn'].delete(*key)
|
|
109
|
+
|
|
110
|
+
return r
|
|
111
|
+
|
|
112
|
+
def exists(self, key, servers = None, prefix = None):
|
|
113
|
+
r = {}
|
|
114
|
+
|
|
115
|
+
if not servers:
|
|
116
|
+
servers = self.servers
|
|
117
|
+
|
|
118
|
+
if not isinstance(key, (list, tuple)):
|
|
119
|
+
key = [key]
|
|
120
|
+
|
|
121
|
+
for name, server in iteritems(servers):
|
|
122
|
+
if not prefix or name.startswith(prefix):
|
|
123
|
+
r[name] = server['conn'].exists(*key)
|
|
124
|
+
|
|
125
|
+
return r
|
|
126
|
+
|
|
127
|
+
def expire(self, key, xtime, servers = None, prefix = None):
|
|
128
|
+
r = {}
|
|
129
|
+
|
|
130
|
+
if not servers:
|
|
131
|
+
servers = self.servers
|
|
132
|
+
|
|
133
|
+
for name, server in iteritems(servers):
|
|
134
|
+
if (not prefix or name.startswith(prefix)) \
|
|
135
|
+
and server['conn'].exists(key):
|
|
136
|
+
r[name] = server['conn'].expire(key, xtime)
|
|
137
|
+
|
|
138
|
+
return r
|
|
139
|
+
|
|
140
|
+
def hset_key(self, key, field, val, expire = None, servers = None, prefix = None):
|
|
141
|
+
r = {}
|
|
142
|
+
|
|
143
|
+
if not servers:
|
|
144
|
+
servers = self.servers
|
|
145
|
+
|
|
146
|
+
if expire is not None:
|
|
147
|
+
for name, server in iteritems(servers):
|
|
148
|
+
if not prefix or name.startswith(prefix):
|
|
149
|
+
r[name] = server['conn'].hset(key, field, val)
|
|
150
|
+
server['conn'].expire(key, expire)
|
|
151
|
+
else:
|
|
152
|
+
for name, server in iteritems(servers):
|
|
153
|
+
if not prefix or name.startswith(prefix):
|
|
154
|
+
r[name] = server['conn'].hset(key, field, val)
|
|
155
|
+
|
|
156
|
+
return r
|
|
157
|
+
|
|
158
|
+
def hget_key(self, key, field, servers = None, prefix = None):
|
|
159
|
+
if not servers:
|
|
160
|
+
servers = self.servers
|
|
161
|
+
|
|
162
|
+
for name, server in iteritems(servers):
|
|
163
|
+
if (not prefix or name.startswith(prefix)) \
|
|
164
|
+
and server['conn'].exists(key):
|
|
165
|
+
return server['conn'].hget(key, field)
|
|
166
|
+
|
|
167
|
+
return None
|
|
168
|
+
|
|
169
|
+
def hdel_key(self, key, field, servers = None, prefix = None):
|
|
170
|
+
r = {}
|
|
171
|
+
|
|
172
|
+
if not servers:
|
|
173
|
+
servers = self.servers
|
|
174
|
+
|
|
175
|
+
if not isinstance(field, (list, tuple)):
|
|
176
|
+
field = [field]
|
|
177
|
+
|
|
178
|
+
for name, server in iteritems(servers):
|
|
179
|
+
if not prefix or name.startswith(prefix):
|
|
180
|
+
r[name] = server['conn'].hdel(key, *field)
|
|
181
|
+
|
|
182
|
+
return r
|
|
183
|
+
|
|
184
|
+
def has_key(self, key, servers = None, prefix = None):
|
|
185
|
+
if not servers:
|
|
186
|
+
servers = self.servers
|
|
187
|
+
|
|
188
|
+
for name, server in iteritems(servers):
|
|
189
|
+
if not prefix or name.startswith(prefix):
|
|
190
|
+
return server['conn'].exists(key)
|
|
191
|
+
|
|
192
|
+
return None
|
|
193
|
+
|
|
194
|
+
def keys(self, pattern = '*', servers = None, prefix = None):
|
|
195
|
+
r = {}
|
|
196
|
+
|
|
197
|
+
if not servers:
|
|
198
|
+
servers = self.servers
|
|
199
|
+
|
|
200
|
+
for name, server in iteritems(servers):
|
|
201
|
+
if not prefix or name.startswith(prefix):
|
|
202
|
+
r[name] = server['conn'].keys(pattern)
|
|
203
|
+
|
|
204
|
+
return r
|
|
205
|
+
|
|
206
|
+
def sadd(self, key, member, servers = None, prefix = None):
|
|
207
|
+
r = {}
|
|
208
|
+
|
|
209
|
+
if not servers:
|
|
210
|
+
servers = self.servers
|
|
211
|
+
|
|
212
|
+
if not isinstance(member, (list, tuple)):
|
|
213
|
+
member = [member]
|
|
214
|
+
|
|
215
|
+
for name, server in iteritems(servers):
|
|
216
|
+
if not prefix or name.startswith(prefix):
|
|
217
|
+
r[name] = server['conn'].sadd(key, *member)
|
|
218
|
+
|
|
219
|
+
return r
|
|
220
|
+
|
|
221
|
+
def srem(self, key, member, servers = None, prefix = None):
|
|
222
|
+
r = {}
|
|
223
|
+
|
|
224
|
+
if not servers:
|
|
225
|
+
servers = self.servers
|
|
226
|
+
|
|
227
|
+
if not isinstance(member, (list, tuple)):
|
|
228
|
+
member = [member]
|
|
229
|
+
|
|
230
|
+
for name, server in iteritems(servers):
|
|
231
|
+
if not prefix or name.startswith(prefix):
|
|
232
|
+
r[name] = server['conn'].srem(key, *member)
|
|
233
|
+
|
|
234
|
+
return r
|
|
235
|
+
|
|
236
|
+
# pylint: disable=too-many-arguments
|
|
237
|
+
def sort(self, key, start = None, num = None, by = None, get = None,
|
|
238
|
+
desc = False, alpha = False, store = None,
|
|
239
|
+
servers = None, prefix = None):
|
|
240
|
+
|
|
241
|
+
r = {}
|
|
242
|
+
|
|
243
|
+
if not servers:
|
|
244
|
+
servers = self.servers
|
|
245
|
+
|
|
246
|
+
for name, server in iteritems(servers):
|
|
247
|
+
if not prefix or name.startswith(prefix):
|
|
248
|
+
r[name] = server['conn'].sort(name = key,
|
|
249
|
+
start = start,
|
|
250
|
+
num = num,
|
|
251
|
+
by = by,
|
|
252
|
+
get = get,
|
|
253
|
+
desc = desc,
|
|
254
|
+
alpha = alpha,
|
|
255
|
+
store = store)
|
|
256
|
+
|
|
257
|
+
return r
|
|
258
|
+
|
|
259
|
+
def disconnect(self, name = None, prefix = None, servers = None):
|
|
260
|
+
if not servers:
|
|
261
|
+
servers = self.servers
|
|
262
|
+
|
|
263
|
+
if name:
|
|
264
|
+
if not servers.get(name) or not servers[name]['conn']:
|
|
265
|
+
return self
|
|
266
|
+
|
|
267
|
+
try:
|
|
268
|
+
servers[name]['conn'].connection_pool.disconnect()
|
|
269
|
+
except Exception:
|
|
270
|
+
pass
|
|
271
|
+
|
|
272
|
+
servers[name]['conn'] = None
|
|
273
|
+
|
|
274
|
+
return self
|
|
275
|
+
|
|
276
|
+
for cname in iterkeys(self.config['general']['redis']):
|
|
277
|
+
if prefix and not cname.startswith(prefix):
|
|
278
|
+
continue
|
|
279
|
+
elif not servers.get(cname) or not servers[cname]['conn']:
|
|
280
|
+
continue
|
|
281
|
+
|
|
282
|
+
try:
|
|
283
|
+
servers[cname]['conn'].connection_pool.disconnect()
|
|
284
|
+
except Exception:
|
|
285
|
+
pass
|
|
286
|
+
|
|
287
|
+
servers[cname]['conn'] = None
|
|
288
|
+
|
|
289
|
+
return self
|
dwho/classes/__init__.py
ADDED
dwho/classes/abstract.py
ADDED
|
@@ -0,0 +1,237 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2015-2019 Adrien Delle Cave
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
"""dwho.classes.abstract"""
|
|
5
|
+
|
|
6
|
+
import abc
|
|
7
|
+
import re
|
|
8
|
+
|
|
9
|
+
try:
|
|
10
|
+
from threading import _get_ident as thread_get_ident
|
|
11
|
+
except ImportError:
|
|
12
|
+
from threading import get_ident as thread_get_ident
|
|
13
|
+
|
|
14
|
+
from threading import _active_limbo_lock, _active
|
|
15
|
+
from six import iterkeys, iteritems, string_types
|
|
16
|
+
|
|
17
|
+
from sonicprobe.libs import anysql
|
|
18
|
+
|
|
19
|
+
_RE_MATCH_OBJECT_FUNCS = ('match', 'search')
|
|
20
|
+
_PARAMS_DICT_MODIFIERS_MATCH = re.compile(r'^(?:(?P<modifiers>[\+\-~=%]+)\s)?(?P<key>.+)$').match
|
|
21
|
+
_PARAM_REGEX_OPTS = ('default', 'func', 'return', 'return_args')
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
class DWhoAbstractHelper(object): # pylint: disable=useless-object-inheritance,too-few-public-methods
|
|
25
|
+
__metaclass__ = abc.ABCMeta
|
|
26
|
+
|
|
27
|
+
@classmethod
|
|
28
|
+
def _parse_re_flags(cls, flags):
|
|
29
|
+
if isinstance(flags, int):
|
|
30
|
+
return flags
|
|
31
|
+
|
|
32
|
+
if isinstance(flags, list):
|
|
33
|
+
r = 0
|
|
34
|
+
for x in flags:
|
|
35
|
+
r |= cls._parse_re_flags(x)
|
|
36
|
+
return r
|
|
37
|
+
|
|
38
|
+
if isinstance(flags, string_types):
|
|
39
|
+
if flags.isdigit():
|
|
40
|
+
return int(flags)
|
|
41
|
+
return getattr(re, flags)
|
|
42
|
+
|
|
43
|
+
return 0
|
|
44
|
+
|
|
45
|
+
@classmethod
|
|
46
|
+
def _param_regex(cls, args, value):
|
|
47
|
+
args = args.copy()
|
|
48
|
+
func = args.get('func') or 'sub'
|
|
49
|
+
rfunc = args.get('return')
|
|
50
|
+
rargs = args.get('return_args')
|
|
51
|
+
is_match_obj = func in _RE_MATCH_OBJECT_FUNCS
|
|
52
|
+
|
|
53
|
+
if is_match_obj and not rfunc:
|
|
54
|
+
rfunc = 'group'
|
|
55
|
+
rargs = [1]
|
|
56
|
+
|
|
57
|
+
if is_match_obj and not rargs:
|
|
58
|
+
rargs = [1]
|
|
59
|
+
|
|
60
|
+
for x in _PARAM_REGEX_OPTS:
|
|
61
|
+
if x in args:
|
|
62
|
+
del args[x]
|
|
63
|
+
|
|
64
|
+
if 'pattern' in args:
|
|
65
|
+
flags = 0
|
|
66
|
+
if 'flags' in args:
|
|
67
|
+
flags = cls._parse_re_flags(args.pop('flags'))
|
|
68
|
+
func = getattr(re.compile(pattern = args.pop('pattern'),
|
|
69
|
+
flags = flags),
|
|
70
|
+
func)
|
|
71
|
+
else:
|
|
72
|
+
func = getattr(re, func)
|
|
73
|
+
|
|
74
|
+
args['string'] = value
|
|
75
|
+
ret = func(**args)
|
|
76
|
+
|
|
77
|
+
if ret is None:
|
|
78
|
+
return ''
|
|
79
|
+
|
|
80
|
+
if not rfunc:
|
|
81
|
+
return ret
|
|
82
|
+
|
|
83
|
+
if rargs:
|
|
84
|
+
return getattr(ret, rfunc)(*rargs)
|
|
85
|
+
|
|
86
|
+
return getattr(ret, rfunc)()
|
|
87
|
+
|
|
88
|
+
@classmethod
|
|
89
|
+
def _build_params_dict(cls, name, cfg, values = None, xvars = None, r = None):
|
|
90
|
+
if not isinstance(values, dict):
|
|
91
|
+
values = {}
|
|
92
|
+
|
|
93
|
+
if not isinstance(r, dict):
|
|
94
|
+
r = {}
|
|
95
|
+
|
|
96
|
+
if not cfg or not isinstance(cfg, list):
|
|
97
|
+
return r
|
|
98
|
+
|
|
99
|
+
fkwargs = {name: values.copy()}
|
|
100
|
+
|
|
101
|
+
if isinstance(xvars, dict):
|
|
102
|
+
fkwargs.update(xvars)
|
|
103
|
+
|
|
104
|
+
for elt in cfg:
|
|
105
|
+
ename = list(elt.keys())[0]
|
|
106
|
+
m = _PARAMS_DICT_MODIFIERS_MATCH(ename)
|
|
107
|
+
if m:
|
|
108
|
+
modifiers = m.group('modifiers') or '+'
|
|
109
|
+
key = m.group('key')
|
|
110
|
+
else:
|
|
111
|
+
modifiers = '+'
|
|
112
|
+
key = ename
|
|
113
|
+
|
|
114
|
+
if '+' in modifiers:
|
|
115
|
+
r[key] = elt[ename]
|
|
116
|
+
elif '-' in modifiers:
|
|
117
|
+
if key not in r:
|
|
118
|
+
continue
|
|
119
|
+
if elt[ename] in (None, r[key]):
|
|
120
|
+
del r[key]
|
|
121
|
+
elif '~' in modifiers:
|
|
122
|
+
args = elt[ename]
|
|
123
|
+
|
|
124
|
+
if key not in r:
|
|
125
|
+
r[key] = args.get('default') or ''
|
|
126
|
+
else:
|
|
127
|
+
r[key] = cls._param_regex(args, r[key])
|
|
128
|
+
elif '=' in modifiers:
|
|
129
|
+
if key in r:
|
|
130
|
+
r[elt[ename]] = r[key]
|
|
131
|
+
|
|
132
|
+
if '{' in modifiers and '}' in modifiers:
|
|
133
|
+
r[key] = r[key].format(**fkwargs)
|
|
134
|
+
|
|
135
|
+
return r
|
|
136
|
+
|
|
137
|
+
|
|
138
|
+
class DWhoAbstractDB(object): # pylint: disable=useless-object-inheritance
|
|
139
|
+
__metaclass__ = abc.ABCMeta
|
|
140
|
+
|
|
141
|
+
def __init__(self):
|
|
142
|
+
self.config = {}
|
|
143
|
+
self._db = {}
|
|
144
|
+
|
|
145
|
+
@property
|
|
146
|
+
def db(self):
|
|
147
|
+
thread_id = thread_get_ident()
|
|
148
|
+
if thread_id not in self._db:
|
|
149
|
+
self._db[thread_id] = {}
|
|
150
|
+
|
|
151
|
+
return self._db[thread_id]
|
|
152
|
+
|
|
153
|
+
@db.setter
|
|
154
|
+
def db(self, value):
|
|
155
|
+
with _active_limbo_lock:
|
|
156
|
+
for tid, db in iteritems(self._db):
|
|
157
|
+
if tid in _active:
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
for name in iterkeys(db):
|
|
161
|
+
self.db_disconnect(name, db)
|
|
162
|
+
|
|
163
|
+
thread_id = thread_get_ident()
|
|
164
|
+
if thread_id not in self._db:
|
|
165
|
+
self._db[thread_id] = {}
|
|
166
|
+
|
|
167
|
+
self._db[thread_id] = value
|
|
168
|
+
|
|
169
|
+
def db_connect(self, name):
|
|
170
|
+
if name not in self.db:
|
|
171
|
+
self.db[name] = {'conn': None, 'cursor': None}
|
|
172
|
+
|
|
173
|
+
if not self.db[name]['conn'] or not self.db[name]['conn'].is_connected(self.db[name]['cursor']):
|
|
174
|
+
if self.db[name]['cursor']:
|
|
175
|
+
try:
|
|
176
|
+
self.db[name]['cursor'].close()
|
|
177
|
+
except Exception:
|
|
178
|
+
pass
|
|
179
|
+
self.db[name]['cursor'] = None
|
|
180
|
+
|
|
181
|
+
if self.db[name]['conn']:
|
|
182
|
+
try:
|
|
183
|
+
self.db[name]['conn'].close()
|
|
184
|
+
except Exception:
|
|
185
|
+
pass
|
|
186
|
+
|
|
187
|
+
self.db[name]['conn'] = anysql.connect_by_uri(self.config['general']["db_uri_%s" % name])
|
|
188
|
+
|
|
189
|
+
if not self.db[name]['cursor']:
|
|
190
|
+
self.db[name]['cursor'] = self.db[name]['conn'].cursor()
|
|
191
|
+
|
|
192
|
+
return self.db[name]
|
|
193
|
+
|
|
194
|
+
@staticmethod
|
|
195
|
+
def get_column_name(column):
|
|
196
|
+
return (".%s" % column).split('.', 2)[-1]
|
|
197
|
+
|
|
198
|
+
def db_prepare_column(self, res, column = None):
|
|
199
|
+
if column:
|
|
200
|
+
prep_method = "_prepcol_%s" % self.get_column_name(column)
|
|
201
|
+
if hasattr(self, prep_method):
|
|
202
|
+
return getattr(self, prep_method)(column, res)
|
|
203
|
+
|
|
204
|
+
if not isinstance(res, object) \
|
|
205
|
+
or res is None \
|
|
206
|
+
or isinstance(res, string_types):
|
|
207
|
+
return res
|
|
208
|
+
|
|
209
|
+
return "%s" % res
|
|
210
|
+
|
|
211
|
+
def db_disconnect(self, name, db = None):
|
|
212
|
+
if not db:
|
|
213
|
+
if not self.db:
|
|
214
|
+
self.db = {name: {'conn': None,
|
|
215
|
+
'cursor': None}}
|
|
216
|
+
db = self.db
|
|
217
|
+
|
|
218
|
+
if not db:
|
|
219
|
+
return self
|
|
220
|
+
|
|
221
|
+
if db[name]['cursor']:
|
|
222
|
+
try:
|
|
223
|
+
db[name]['cursor'].close()
|
|
224
|
+
except Exception:
|
|
225
|
+
pass
|
|
226
|
+
|
|
227
|
+
db[name]['cursor'] = None
|
|
228
|
+
|
|
229
|
+
if db[name]['conn']:
|
|
230
|
+
try:
|
|
231
|
+
db[name]['conn'].close()
|
|
232
|
+
except Exception:
|
|
233
|
+
pass
|
|
234
|
+
|
|
235
|
+
db[name]['conn'] = None
|
|
236
|
+
|
|
237
|
+
return self
|
dwho/classes/errors.py
ADDED
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# Copyright (C) 2015-2019 Adrien Delle Cave
|
|
3
|
+
# SPDX-License-Identifier: GPL-3.0-or-later
|
|
4
|
+
"""dwho.classes.errors"""
|
|
5
|
+
|
|
6
|
+
from pyinotify import PyinotifyError
|
|
7
|
+
|
|
8
|
+
|
|
9
|
+
class DWhoError(Exception):
|
|
10
|
+
pass
|
|
11
|
+
|
|
12
|
+
class DWhoConfigurationError(DWhoError):
|
|
13
|
+
pass
|
|
14
|
+
|
|
15
|
+
class DWhoInotifyError(PyinotifyError):
|
|
16
|
+
pass
|