kongalib 2.0.5__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.
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
+