kongalib 2.0.4__cp314-cp314-macosx_10_15_universal2.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.
Potentially problematic release.
This version of kongalib might be problematic. Click here for more details.
- _kongalib.cpython-314-darwin.so +0 -0
- kongalib/__init__.py +394 -0
- kongalib/async_client.py +813 -0
- kongalib/client.py +1045 -0
- kongalib/constants.json +1 -0
- kongalib/constants.py +187 -0
- kongalib/data_dictionary.py +203 -0
- kongalib/db.py +267 -0
- kongalib/expression.py +841 -0
- kongalib/json.py +114 -0
- kongalib/lex.py +1058 -0
- kongalib/scripting.py +766 -0
- kongalib/yacc.py +3276 -0
- kongalib-2.0.4.dist-info/METADATA +150 -0
- kongalib-2.0.4.dist-info/RECORD +21 -0
- kongalib-2.0.4.dist-info/WHEEL +6 -0
- kongalib-2.0.4.dist-info/licenses/LICENSE +165 -0
- kongalib-2.0.4.dist-info/top_level.txt +4 -0
- kongalib-2.0.4.dist-info/zip-safe +1 -0
- kongaui.py +507 -0
- kongautil.py +581 -0
|
Binary file
|
kongalib/__init__.py
ADDED
|
@@ -0,0 +1,394 @@
|
|
|
1
|
+
# -*- coding: utf-8 -*-
|
|
2
|
+
# _ _ _ _
|
|
3
|
+
# | | | (_) |
|
|
4
|
+
# | | _____ _ __ __ _ __ _| |_| |__
|
|
5
|
+
# | |/ / _ \| '_ \ / _` |/ _` | | | '_ \
|
|
6
|
+
# | < (_) | | | | (_| | (_| | | | |_) |
|
|
7
|
+
# |_|\_\___/|_| |_|\__, |\__,_|_|_|_.__/
|
|
8
|
+
# __/ |
|
|
9
|
+
# |___/
|
|
10
|
+
#
|
|
11
|
+
# Konga client library, by EasyByte Software
|
|
12
|
+
#
|
|
13
|
+
# https://github.com/easybyte-software/kongalib
|
|
14
|
+
|
|
15
|
+
|
|
16
|
+
from __future__ import print_function
|
|
17
|
+
from __future__ import absolute_import
|
|
18
|
+
|
|
19
|
+
import sys
|
|
20
|
+
import traceback
|
|
21
|
+
import atexit
|
|
22
|
+
|
|
23
|
+
DEFAULT_DISCOVER_TIMEOUT = 5000
|
|
24
|
+
DEFAULT_CONNECT_TIMEOUT = 30000
|
|
25
|
+
DEFAULT_EXECUTE_TIMEOUT = 10000
|
|
26
|
+
|
|
27
|
+
CRYPT_NONE = 0
|
|
28
|
+
CRYPT_LOW = 1
|
|
29
|
+
CRYPT_NORMAL = 2
|
|
30
|
+
CRYPT_HIGH = 3
|
|
31
|
+
|
|
32
|
+
PROGRESS_PROCESS = 0
|
|
33
|
+
PROGRESS_SEND = 1
|
|
34
|
+
PROGRESS_EXECUTE = 2
|
|
35
|
+
PROGRESS_RECEIVE = 3
|
|
36
|
+
PROGRESS_COMPLETE = 4
|
|
37
|
+
|
|
38
|
+
NIC_UP = 0x1
|
|
39
|
+
NIC_CAN_BROADCAST = 0x2
|
|
40
|
+
NIC_CAN_MULTICAST = 0x4
|
|
41
|
+
NIC_IS_LOOPBACK = 0x8
|
|
42
|
+
|
|
43
|
+
PROGRESS_INDEFINITE = -1.0
|
|
44
|
+
|
|
45
|
+
ROUND = 1
|
|
46
|
+
FLOOR = 2
|
|
47
|
+
CEIL = 3
|
|
48
|
+
|
|
49
|
+
BACKUP_ON_COMPUTER = 0x1 #: Il backup è posizionato in locale sulla macchina corrente
|
|
50
|
+
BACKUP_ON_CLOUD = 0x2 #: Il backup è posizionato nel cloud
|
|
51
|
+
|
|
52
|
+
|
|
53
|
+
|
|
54
|
+
class Log(object):
|
|
55
|
+
"""La classe Log serve ad immagazzinare i messaggi prodotti dal server durante un'operazione; oggetti di questa classe
|
|
56
|
+
vengono popolati durante le chiamate asincrone della classe :class:`~kongalib.Client`.
|
|
57
|
+
"""
|
|
58
|
+
|
|
59
|
+
INFO = 0 #: Costante che identifica i messaggi di tipo informativo
|
|
60
|
+
WARNING = 1 #: Costante che identifica i messaggi di tipo avviso
|
|
61
|
+
ERROR = 2 #: Costante che identifica i messaggi di tipo errore
|
|
62
|
+
|
|
63
|
+
def __init__(self, title=''):
|
|
64
|
+
self.title = title
|
|
65
|
+
self.messages = []
|
|
66
|
+
self.clear()
|
|
67
|
+
self.state_stack = []
|
|
68
|
+
|
|
69
|
+
def save(self):
|
|
70
|
+
"""Salva lo stato del log"""
|
|
71
|
+
self.state_stack.append((self.errors, self.warnings, len(self.messages)))
|
|
72
|
+
|
|
73
|
+
def restore(self):
|
|
74
|
+
"""Ripristina il log allo stesso stato in cui si trovava prima dell'ultima chiamata al metodo :meth:`save`."""
|
|
75
|
+
self.errors, self.warning, count = self.state_stack.pop()
|
|
76
|
+
self.messages[count:] = []
|
|
77
|
+
|
|
78
|
+
def clear(self):
|
|
79
|
+
"""Elimina tutti i messaggi presenti sul log."""
|
|
80
|
+
self.messages[:] = []
|
|
81
|
+
self.errors = False
|
|
82
|
+
self.warnings = False
|
|
83
|
+
|
|
84
|
+
def add_message(self, type, msg, name=None, row=None, colname=None):
|
|
85
|
+
"""Aggiunge un messaggio *msg* di tipo *type*."""
|
|
86
|
+
if type < Log.INFO or type > Log.ERROR:
|
|
87
|
+
type = Log.ERROR
|
|
88
|
+
self.messages.append((type, msg, name, row, colname))
|
|
89
|
+
if type == Log.WARNING:
|
|
90
|
+
self.warnings = True
|
|
91
|
+
elif type == Log.ERROR:
|
|
92
|
+
self.errors = True
|
|
93
|
+
|
|
94
|
+
def info(self, message, name=None, row=None, colname=None):
|
|
95
|
+
"""Esattamente come chiamare ``add_message(Log.INFO, message)``."""
|
|
96
|
+
self.add_message(Log.INFO, message, name, row, colname)
|
|
97
|
+
|
|
98
|
+
def warning(self, message, name=None, row=None, colname=None):
|
|
99
|
+
"""Esattamente come chiamare ``add_message(Log.WARNING, message)``."""
|
|
100
|
+
self.add_message(Log.WARNING, message, name, row, colname)
|
|
101
|
+
|
|
102
|
+
def error(self, message, name=None, row=None, colname=None):
|
|
103
|
+
"""Esattamente come chiamare ``add_message(Log.ERROR, message)``."""
|
|
104
|
+
self.add_message(Log.ERROR, message, name, row, colname)
|
|
105
|
+
|
|
106
|
+
def exception(self, e):
|
|
107
|
+
"""Aggiunge una eccezione come messaggio di errore sul log."""
|
|
108
|
+
self.error(Log.ERROR, ensure_text(e))
|
|
109
|
+
|
|
110
|
+
def has_messages(self):
|
|
111
|
+
"""Controlla la presenza di messaggi di qualsiasi tipo sul log."""
|
|
112
|
+
return len(self.messages) > 0
|
|
113
|
+
|
|
114
|
+
def has_warnings(self):
|
|
115
|
+
"""Controlla la presenza di messaggi di tipo :attr:`WARNING` sul log."""
|
|
116
|
+
return self.warnings
|
|
117
|
+
|
|
118
|
+
def has_errors(self):
|
|
119
|
+
"""Controlla la presenza di messaggi di tipo :attr:`ERROR` sul log."""
|
|
120
|
+
return self.errors
|
|
121
|
+
|
|
122
|
+
def get_messages(self, type=None):
|
|
123
|
+
"""Ottiene la lista dei messaggi sul log. Se *type* è ``None``, tutti i messaggi vengono restituiti, altrimenti solo i messaggi di
|
|
124
|
+
un determinato tipo."""
|
|
125
|
+
if type is None:
|
|
126
|
+
return self.messages
|
|
127
|
+
return [ msg for msg in self.messages if msg[0] == type ]
|
|
128
|
+
|
|
129
|
+
def add_messages(self, messages):
|
|
130
|
+
for msg in messages:
|
|
131
|
+
self.add_message(*msg)
|
|
132
|
+
|
|
133
|
+
def get_exception(self, klass=RuntimeError):
|
|
134
|
+
error = self.get_messages(Log.ERROR)[0][1]
|
|
135
|
+
return klass(error)
|
|
136
|
+
|
|
137
|
+
def extend(self, log):
|
|
138
|
+
for msg in log.get_messages():
|
|
139
|
+
self.add_message(*msg)
|
|
140
|
+
|
|
141
|
+
def strip_html(self, html):
|
|
142
|
+
"""Elimina tutto il codice HTML dalla stringa in *html*, lasciando solo le parti testuali."""
|
|
143
|
+
from html.parser import HTMLParser
|
|
144
|
+
|
|
145
|
+
class Stripper(HTMLParser):
|
|
146
|
+
def __init__(self):
|
|
147
|
+
self.convert_charrefs = True
|
|
148
|
+
self.reset()
|
|
149
|
+
self.fed = []
|
|
150
|
+
self.feed(html)
|
|
151
|
+
def handle_starttag(self, tag, attrs):
|
|
152
|
+
if tag == 'br':
|
|
153
|
+
self.fed.append('\n')
|
|
154
|
+
def handle_startendtag(self, tag, attrs):
|
|
155
|
+
if tag == 'br':
|
|
156
|
+
self.fed.append('\n')
|
|
157
|
+
def handle_data(self, d):
|
|
158
|
+
self.fed.append(d)
|
|
159
|
+
def get_data(self):
|
|
160
|
+
return ''.join(self.fed)
|
|
161
|
+
return Stripper().get_data()
|
|
162
|
+
|
|
163
|
+
def format_message(self, message):
|
|
164
|
+
"""Ritorna *message* formattato correttamente per essere visualizzato. *message* deve essere una tupla di almeno due elementi:
|
|
165
|
+
``(tipo, testo)``, dove ``tipo`` è uno tra :attr:`INFO`, :attr:`WARNING` ed :attr:`ERROR`, mentre ``testo`` è il corpo del messaggio,
|
|
166
|
+
che può includere codice HTML (che verrà soppresso nella formattazione)."""
|
|
167
|
+
type = ('INFO', 'WARNING', 'ERROR')
|
|
168
|
+
msg = ensure_text(self.strip_html(message[1]))
|
|
169
|
+
return u'[%s] %s' % (type[message[0]], msg)
|
|
170
|
+
|
|
171
|
+
def dumps(self):
|
|
172
|
+
"""Esegue un dump dei messaggi presenti sul log e restituisce un'unica stringa. Eventuale codice HTML presente nei messaggi è eliminato
|
|
173
|
+
usando :meth:`strip_html`."""
|
|
174
|
+
return u'\n'.join([ self.format_message(message) for message in self.messages ])
|
|
175
|
+
|
|
176
|
+
def dump(self, logger=None):
|
|
177
|
+
"""Esattamente come :meth:`dumps` ma stampa il dump su ``stdout``. Se ``logger`` è un'istanza di ``logging.Logger``, verrà usata per l'output
|
|
178
|
+
invece di ``stdout``."""
|
|
179
|
+
if logger is None:
|
|
180
|
+
print(self.dumps())
|
|
181
|
+
else:
|
|
182
|
+
for message in self.get_messages():
|
|
183
|
+
method = {
|
|
184
|
+
Log.ERROR: logger.error,
|
|
185
|
+
Log.WARNING: logger.warning,
|
|
186
|
+
}.get(message[0], logger.info)
|
|
187
|
+
method(ensure_text(self.strip_html(message[1])))
|
|
188
|
+
|
|
189
|
+
|
|
190
|
+
|
|
191
|
+
class Error(Exception):
|
|
192
|
+
"""Rappresenza un errore generico generato dal server Konga. Eccezioni di questo tipo hanno due attributi:
|
|
193
|
+
|
|
194
|
+
.. attribute:: errno
|
|
195
|
+
|
|
196
|
+
Codice identificativo dell'errore
|
|
197
|
+
|
|
198
|
+
.. attribute:: error
|
|
199
|
+
|
|
200
|
+
Stringa che descrive l'errore
|
|
201
|
+
"""
|
|
202
|
+
def __init__(self, errno, msg):
|
|
203
|
+
self.errno = errno
|
|
204
|
+
self.error = self.msg = msg
|
|
205
|
+
def __str__(self):
|
|
206
|
+
msg = self.msg and ('%s' % self.msg) or '(internal error)'
|
|
207
|
+
return ensure_text(msg)
|
|
208
|
+
def __repr__(self):
|
|
209
|
+
return '<Error %d: %s>' % (self.errno, str(self))
|
|
210
|
+
|
|
211
|
+
|
|
212
|
+
|
|
213
|
+
class ErrorList(Error):
|
|
214
|
+
"""Rappresenza una lista di errori generati dal server Konga. Eccezioni di questo tipo hanno tre attributi:
|
|
215
|
+
|
|
216
|
+
.. attribute:: errno
|
|
217
|
+
|
|
218
|
+
Codice identificativo dell'ultimo errore
|
|
219
|
+
|
|
220
|
+
.. attribute:: error
|
|
221
|
+
|
|
222
|
+
Stringa che descrive l'ultimo errore
|
|
223
|
+
|
|
224
|
+
.. attribute:: errors
|
|
225
|
+
|
|
226
|
+
Lista degli errori, in cui ogni errore è una tupla nella forma ``(type, errno, prefix, error)``; *type* è uno tra :attr:`Log.INFO`,
|
|
227
|
+
:attr:`Log.WARNING` e :attr:`Log.ERROR`; *errno* ed *error* sono il codice e la descrizione dell'errore, e *prefix* un eventuale
|
|
228
|
+
prefisso che identifica il contesto dell'errore.
|
|
229
|
+
"""
|
|
230
|
+
|
|
231
|
+
PREPARE_CALLBACK = None
|
|
232
|
+
|
|
233
|
+
def __init__(self, errors=None):
|
|
234
|
+
self.errors = errors or []
|
|
235
|
+
self.errno = OK
|
|
236
|
+
self.error = 'No error'
|
|
237
|
+
for type, errno, prefix, error in self.errors:
|
|
238
|
+
if type == Log.ERROR:
|
|
239
|
+
self.errno = errno
|
|
240
|
+
self.error = error
|
|
241
|
+
break
|
|
242
|
+
|
|
243
|
+
def __str__(self):
|
|
244
|
+
return u'\n'.join([ ensure_text(e) for e in self.get_errors() ])
|
|
245
|
+
|
|
246
|
+
def __repr__(self):
|
|
247
|
+
return '<ErrorList: %s>' % repr(self.get_errors())
|
|
248
|
+
|
|
249
|
+
def __iter__(self):
|
|
250
|
+
return iter(self.errors)
|
|
251
|
+
|
|
252
|
+
def get_errors(self):
|
|
253
|
+
return [ Error(errno, error) for type, errno, prefix, error in self.errors ]
|
|
254
|
+
|
|
255
|
+
def add_error(self, errno, error, prefix=''):
|
|
256
|
+
"""Aggiunge un errore (tipo :attr:`Log.ERROR`) al log, assegnando il codice e la descrizione da *errno* ed *error*.
|
|
257
|
+
*prefix* è una stringa di prefisso e può essere usato per dare un contesto all'errore.
|
|
258
|
+
"""
|
|
259
|
+
self.errors.append((Log.ERROR, errno, prefix, error))
|
|
260
|
+
self.errno = errno
|
|
261
|
+
self.error = error
|
|
262
|
+
|
|
263
|
+
def prepare_log(self, log=None):
|
|
264
|
+
"""Trasferisce la lista degli errori su *log* e restituisce il log aggiornato. *log* deve essere un oggetto di classe :class:`~kongalib.Log`;
|
|
265
|
+
se ``None``, un nuovo oggetto :class:`~kongalib.Log` verrà creato e popolato con gli errori.
|
|
266
|
+
"""
|
|
267
|
+
if ErrorList.PREPARE_CALLBACK is not None:
|
|
268
|
+
return ErrorList.PREPARE_CALLBACK(self, log)
|
|
269
|
+
if log is None:
|
|
270
|
+
log = Log()
|
|
271
|
+
for type, errno, prefix, error in self.errors:
|
|
272
|
+
message = '%s (%d)' % (error, errno)
|
|
273
|
+
if prefix:
|
|
274
|
+
message = '%s %s' % (prefix, message)
|
|
275
|
+
log.add_message(type, message)
|
|
276
|
+
return log
|
|
277
|
+
|
|
278
|
+
@classmethod
|
|
279
|
+
def from_error(cls, errno, error, prefix=''):
|
|
280
|
+
"""Costruisce un nuovo oggetto :class:`ErrorList` contenente un singolo errore (tipo :attr:`Log.ERROR`), assegnando il codice e la
|
|
281
|
+
descrizione da *errno* ed *error*. *prefix* è una stringa di prefisso e può essere usato per dare un contesto all'errore.
|
|
282
|
+
"""
|
|
283
|
+
res = ErrorList()
|
|
284
|
+
res.add_error(errno, error, prefix)
|
|
285
|
+
return res
|
|
286
|
+
|
|
287
|
+
@classmethod
|
|
288
|
+
def from_exception(cls, e=None):
|
|
289
|
+
"""Costruisce un nuovo oggetto :class:`ErrorList` contenente un singolo errore (tipo :attr:`Log.ERROR`), a partire dall'eccezione *e*;
|
|
290
|
+
se *e* è ``None``, viene assunta l'eccezione corrente. L'errore creato avrà un codice *errno* valido se *e* è un'eccezione di classe
|
|
291
|
+
:exc:`Error`, altrimenti sarà ``-1``.
|
|
292
|
+
"""
|
|
293
|
+
if e is None:
|
|
294
|
+
e = sys.exc_info()[1]
|
|
295
|
+
if isinstance(e, ErrorList):
|
|
296
|
+
return e
|
|
297
|
+
elif isinstance(e, Error):
|
|
298
|
+
errno = e.errno
|
|
299
|
+
error = e.msg
|
|
300
|
+
else:
|
|
301
|
+
errno = -1
|
|
302
|
+
error = str(e)
|
|
303
|
+
return cls.from_error(errno, error)
|
|
304
|
+
|
|
305
|
+
@classmethod
|
|
306
|
+
def set_prepare_callback(cls, callback):
|
|
307
|
+
cls.PREPARE_CALLBACK = callback
|
|
308
|
+
|
|
309
|
+
|
|
310
|
+
|
|
311
|
+
class JSONError(Exception):
|
|
312
|
+
def __init__(self, msg):
|
|
313
|
+
self.msg = msg
|
|
314
|
+
def __str__(self):
|
|
315
|
+
return ensure_text(self.msg)
|
|
316
|
+
|
|
317
|
+
|
|
318
|
+
|
|
319
|
+
def ensure_text(text, error='replace'):
|
|
320
|
+
if isinstance(text, bytes):
|
|
321
|
+
text = str(text, 'utf-8', 'replace')
|
|
322
|
+
elif not isinstance(text, str):
|
|
323
|
+
text = str(text)
|
|
324
|
+
return text
|
|
325
|
+
|
|
326
|
+
|
|
327
|
+
|
|
328
|
+
from _kongalib import Decimal, Deferred, JSONEncoder, JSONDecoder, NamedSemaphore, start_timer, hash_password, host_lookup, get_network_interfaces, get_machine_uuid, get_system_info, _cleanup, lock, unlock, set_default_idle_callback, set_power_callbacks, checksum, _apply_stylesheet, regexp_find_all, _check_all
|
|
329
|
+
from .constants import *
|
|
330
|
+
from .client import *
|
|
331
|
+
from .expression import *
|
|
332
|
+
from .data_dictionary import *
|
|
333
|
+
from .async_client import AsyncClient
|
|
334
|
+
|
|
335
|
+
|
|
336
|
+
class ErrorMessage(object):
|
|
337
|
+
def __init__(self, errno, error):
|
|
338
|
+
self.errno = errno
|
|
339
|
+
self.error = error
|
|
340
|
+
exc = sys.exc_info()
|
|
341
|
+
if exc is None:
|
|
342
|
+
self.traceback = None
|
|
343
|
+
else:
|
|
344
|
+
self.traceback = ''.join(traceback.format_exception(*exc))
|
|
345
|
+
|
|
346
|
+
def __str__(self):
|
|
347
|
+
return ensure_text(self.error if self.traceback is None else self.traceback)
|
|
348
|
+
|
|
349
|
+
|
|
350
|
+
def _on_destroy_thread():
|
|
351
|
+
import threading
|
|
352
|
+
thread = threading.current_thread()
|
|
353
|
+
thread._Thread__delete()
|
|
354
|
+
|
|
355
|
+
|
|
356
|
+
def round(number, ndigits=2):
|
|
357
|
+
"""Arrotonda *number* a *ndigits* cifre decimali, arrotondando verso 0 se l'ultima cifra dopo l'arrotondamento è compresa tra 0
|
|
358
|
+
e 5, altrimenti arrotonda allontanadosi da 0. Restituisce un oggetto :class:`~kongalib.Decimal`.
|
|
359
|
+
"""
|
|
360
|
+
return Decimal(number).round(10**(-ndigits))
|
|
361
|
+
|
|
362
|
+
def floor(number, ndigits=2):
|
|
363
|
+
"""Arrotonda *number* a *ndigits* cifre decimali, arrotondando verso 0. Restituisce un oggetto :class:`~kongalib.Decimal`."""
|
|
364
|
+
return Decimal(number).floor(10**(-ndigits))
|
|
365
|
+
|
|
366
|
+
def ceil(number, ndigits=2):
|
|
367
|
+
"""Arrotonda *number* a *ndigits* cifre decimali, arrotondando allontanandosi da 0. Restituisce un oggetto :class:`~kongalib.Decimal`."""
|
|
368
|
+
return Decimal(number).ceil(10**(-ndigits))
|
|
369
|
+
|
|
370
|
+
def multiply_and_round(x, y, ndigits=2):
|
|
371
|
+
return Decimal(x).multiply(Decimal(y), 10**(-ndigits), ROUND)
|
|
372
|
+
|
|
373
|
+
def multiply_and_floor(x, y, ndigits=2):
|
|
374
|
+
return Decimal(x).multiply(Decimal(y), 10**(-ndigits), FLOOR)
|
|
375
|
+
|
|
376
|
+
def multiply_and_ceil(x, y, ndigits=2):
|
|
377
|
+
return Decimal(x).multiply(Decimal(y), 10**(-ndigits), CEIL)
|
|
378
|
+
|
|
379
|
+
def divide_and_round(x, y, ndigits=2):
|
|
380
|
+
return Decimal(x).divide(Decimal(y), 10**(-ndigits), ROUND)
|
|
381
|
+
|
|
382
|
+
def divide_and_floor(x, y, ndigits=2):
|
|
383
|
+
return Decimal(x).divide(Decimal(y), 10**(-ndigits), FLOOR)
|
|
384
|
+
|
|
385
|
+
def divide_and_ceil(x, y, ndigits=2):
|
|
386
|
+
return Decimal(x).divide(Decimal(y), 10**(-ndigits), CEIL)
|
|
387
|
+
|
|
388
|
+
def escape(query):
|
|
389
|
+
"""Sostituisce `'` con `''` per preparare una stringa all'inserimento SQL."""
|
|
390
|
+
return query.replace("'", "''")
|
|
391
|
+
|
|
392
|
+
|
|
393
|
+
atexit.register(_cleanup)
|
|
394
|
+
|