kongalib 1.12.0__cp311-cp311-win_amd64.whl → 2.0.0.post1__cp311-cp311-win_amd64.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.cp311-win_amd64.pdb +0 -0
- _kongalib.cp311-win_amd64.pyd +0 -0
- kongalib/__init__.py +22 -36
- kongalib/async_client.py +61 -65
- kongalib/client.py +51 -20
- kongalib/constants.py +110 -1853
- kongalib/data_dictionary.py +3 -12
- kongalib/db.py +7 -8
- kongalib/expression.py +17 -23
- kongalib/json.py +1 -2
- kongalib/scripting.py +38 -27
- {kongalib-1.12.0.dist-info → kongalib-2.0.0.post1.dist-info}/METADATA +29 -26
- kongalib-2.0.0.post1.dist-info/RECORD +21 -0
- {kongalib-1.12.0.dist-info → kongalib-2.0.0.post1.dist-info}/WHEEL +1 -1
- {kongalib-1.12.0.dist-info → kongalib-2.0.0.post1.dist-info}/top_level.txt +1 -0
- kongaui.py +4 -55
- kongautil.py +17 -13
- kongalib/_kongalib.cp311-win_amd64.pdb +0 -0
- kongalib/_kongalib.cp311-win_amd64.pyd +0 -0
- kongalib/compat.py +0 -492
- kongalib-1.12.0.dist-info/RECORD +0 -22
- {kongalib-1.12.0.dist-info → kongalib-2.0.0.post1.dist-info/licenses}/LICENSE +0 -0
- {kongalib-1.12.0.dist-info → kongalib-2.0.0.post1.dist-info}/zip-safe +0 -0
kongalib/data_dictionary.py
CHANGED
|
@@ -15,7 +15,6 @@
|
|
|
15
15
|
|
|
16
16
|
from kongalib import Error, ErrorList
|
|
17
17
|
from .constants import *
|
|
18
|
-
from .compat import *
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
TYPE_TINYINT = 1 #: Tipo di campo SQL TINYINT; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``int``.
|
|
@@ -24,16 +23,7 @@ TYPE_INT = 3 #: Tipo di campo SQL INT; i valori ottenuti dalla :meth:`~ko
|
|
|
24
23
|
TYPE_BIGINT = 4 #: Tipo di campo SQL BIGINT; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``int``.
|
|
25
24
|
TYPE_FLOAT = 5 #: Tipo di campo SQL FLOAT; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``float``.
|
|
26
25
|
TYPE_DOUBLE = 6 #: Tipo di campo SQL DOUBLE; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``float``.
|
|
27
|
-
TYPE_DECIMAL = 7
|
|
28
|
-
"""Tipo di campo SQL DECIMAL; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo :class:`kongalib.Decimal`.
|
|
29
|
-
|
|
30
|
-
.. warning:: Konga Server traduce automaticamente questo tipo di dato in BIGINT sul database SQL, e salva i valori decimali come se
|
|
31
|
-
fossero interi moltiplicati per 1000000. Questo consente una precisione fino a 6 cifre decimali, e permette a Konga Server di operare anche
|
|
32
|
-
con driver SQL che non supportano nativamente il tipo dato DECIMAL (come SQLite). La traduzione è completamente trasparente per kongalib, in
|
|
33
|
-
quanto i metodi della classe :class:`kongalib.Client` ricevono e restituiscono oggetti di clase :class:`kongalib.Decimal` per gestire
|
|
34
|
-
i decimali.
|
|
35
|
-
"""
|
|
36
|
-
|
|
26
|
+
TYPE_DECIMAL = 7 #: Tipo di campo SQL DECIMAL; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo :class:`kongalib.Decimal`.
|
|
37
27
|
TYPE_DATE = 8 #: Tipo di campo SQL DATE; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``datetime.date``.
|
|
38
28
|
TYPE_TIME = 9 #: Tipo di campo SQL TIME; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``datetime.time``.
|
|
39
29
|
TYPE_TIMESTAMP = 10 #: Tipo di campo SQL TIMESTAMP; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``datetime.datetime``.
|
|
@@ -46,6 +36,7 @@ TYPE_LONGTEXT = 16 #: Tipo di campo SQL LONGTEXT; i valori ottenuti dalla :
|
|
|
46
36
|
TYPE_TINYBLOB = 17 #: Tipo di campo SQL TINYBLOB; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``bytes``.
|
|
47
37
|
TYPE_BLOB = 18 #: Tipo di campo SQL BLOB; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``bytes``.
|
|
48
38
|
TYPE_LONGBLOB = 19 #: Tipo di campo SQL LONGBLOB; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``bytes``.
|
|
39
|
+
TYPE_JSON = 20 #: Tipo di campo SQL JSON; i valori ottenuti dalla :meth:`~kongalib.Client.select_data` saranno di tipo ``unicode``.
|
|
49
40
|
|
|
50
41
|
|
|
51
42
|
TABLE_HAS_IMAGES = 0x1 #: Flag informativo di tabella del data dictionary. Se specificato, i record della tabella possono avere immagini collegate.
|
|
@@ -89,7 +80,7 @@ class DataDictionary(object):
|
|
|
89
80
|
|
|
90
81
|
def get_label(self, key):
|
|
91
82
|
"""Ottiene la descrizione della chiave *key* sotto forma di ``dict`` con le traduzioni corrispondenti a ciascuna lingua."""
|
|
92
|
-
if isinstance(key,
|
|
83
|
+
if isinstance(key, str):
|
|
93
84
|
return self.__data[key][1]
|
|
94
85
|
for value, label in self.__data.values():
|
|
95
86
|
if value == key:
|
kongalib/db.py
CHANGED
|
@@ -18,7 +18,6 @@ import datetime
|
|
|
18
18
|
|
|
19
19
|
from kongalib import Client, Decimal, Error as _Error, ErrorList
|
|
20
20
|
from .constants import *
|
|
21
|
-
from .compat import *
|
|
22
21
|
|
|
23
22
|
|
|
24
23
|
apilevel = "2.0" #: Versione delle API, come da specifica
|
|
@@ -142,11 +141,11 @@ class Cursor(object):
|
|
|
142
141
|
self.__description = []
|
|
143
142
|
row = self.__result[0]
|
|
144
143
|
for field, data in zip(fields, row):
|
|
145
|
-
if isinstance(data,
|
|
144
|
+
if isinstance(data, (int, float, Decimal)):
|
|
146
145
|
t = NUMBER
|
|
147
146
|
elif isinstance(data, (datetime.date, datetime.datetime)):
|
|
148
147
|
t = DATETIME
|
|
149
|
-
elif isinstance(data,
|
|
148
|
+
elif isinstance(data, str):
|
|
150
149
|
t = STRING
|
|
151
150
|
else:
|
|
152
151
|
t = BINARY
|
|
@@ -251,14 +250,14 @@ def TimeFromTicks(ticks):
|
|
|
251
250
|
def TimestampFromTicks(ticks):
|
|
252
251
|
return Timestamp(*time.localtime(ticks)[:6])
|
|
253
252
|
|
|
254
|
-
def connect(host, port=0, driver=None, database=None, user=None, password=None):
|
|
255
|
-
"""Esegue una connessione al server Konga identificato da *host* e *port*,
|
|
256
|
-
ed infine si autentica usando *user* e *password*. Restituisce un oggetto :class:`Connection`; da questo
|
|
257
|
-
:class:`Cursor` che permette di eseguire query SQL sul database aperto sulla connessione.
|
|
253
|
+
def connect(host, port=0, driver=None, database=None, user=None, password=None, tenant_key=None):
|
|
254
|
+
"""Esegue una connessione al server Konga identificato da *host* e *port*, usando l'eventuale chiave tenant *tenant_key*, apre *database*
|
|
255
|
+
usando il *driver* specificato, ed infine si autentica usando *user* e *password*. Restituisce un oggetto :class:`Connection`; da questo
|
|
256
|
+
è possibile ottenere un oggetto :class:`Cursor` che permette di eseguire query SQL sul database aperto sulla connessione.
|
|
258
257
|
"""
|
|
259
258
|
conn = Connection()
|
|
260
259
|
try:
|
|
261
|
-
conn.connect({ 'host': host, 'port': port })
|
|
260
|
+
conn.connect({ 'host': host, 'port': port }, options={ 'tenant_key': tenant_key })
|
|
262
261
|
conn.open_database(driver, database)
|
|
263
262
|
conn.authenticate(user, password)
|
|
264
263
|
except _Error as e:
|
kongalib/expression.py
CHANGED
|
@@ -20,8 +20,9 @@ import re
|
|
|
20
20
|
import io
|
|
21
21
|
import tempfile
|
|
22
22
|
import collections
|
|
23
|
+
from xml.etree import ElementTree as ET
|
|
23
24
|
|
|
24
|
-
from
|
|
25
|
+
from kongalib import ensure_text
|
|
25
26
|
|
|
26
27
|
|
|
27
28
|
|
|
@@ -202,6 +203,10 @@ def parse(sql):
|
|
|
202
203
|
def p_expression_binop(p):
|
|
203
204
|
'expression : ID OPERAND VALUE'
|
|
204
205
|
p[0] = Operand(p[1], p[2], p[3])
|
|
206
|
+
|
|
207
|
+
def p_expression_valueop(p):
|
|
208
|
+
'expression : VALUE OPERAND VALUE'
|
|
209
|
+
p[0] = Operand(p[1], p[2], p[3], _HasLogic.LOGIC_NONE, _HasLogic.FLAG_NO_ESCAPE)
|
|
205
210
|
|
|
206
211
|
def p_expression_func_fieldop(p):
|
|
207
212
|
'expression : function OPERAND ID'
|
|
@@ -366,7 +371,7 @@ class Operand(_HasLogic):
|
|
|
366
371
|
def __hash__(self):
|
|
367
372
|
return hash(str(self))
|
|
368
373
|
|
|
369
|
-
def
|
|
374
|
+
def __str__(self):
|
|
370
375
|
if self.value is None:
|
|
371
376
|
value = 'NULL'
|
|
372
377
|
elif re.match(r'^(\-)?[0-9]+$', self.value):
|
|
@@ -381,12 +386,6 @@ class Operand(_HasLogic):
|
|
|
381
386
|
value = "'%s'" % self.value.replace("'", "''")
|
|
382
387
|
return (u'%s %s %s' % (ensure_text(self.column), ensure_text(self.operator), ensure_text(value)))
|
|
383
388
|
|
|
384
|
-
def __str__(self):
|
|
385
|
-
if PY3:
|
|
386
|
-
return self.__unicode__()
|
|
387
|
-
else:
|
|
388
|
-
return self.__unicode__().encode('utf-8')
|
|
389
|
-
|
|
390
389
|
def __repr__(self):
|
|
391
390
|
return str(self)
|
|
392
391
|
|
|
@@ -519,7 +518,7 @@ class OperandIsNotNull(Operand):
|
|
|
519
518
|
|
|
520
519
|
class OperandIN(OperandNE):
|
|
521
520
|
def __init__(self, column, value):
|
|
522
|
-
if not isinstance(value,
|
|
521
|
+
if not isinstance(value, str):
|
|
523
522
|
value = u"('%s')" % (u"', '".join([ ensure_text(x).replace("'", "''") for x in value]))
|
|
524
523
|
Operand.__init__(self, column, 'IN', value, _HasLogic.LOGIC_NONE, _HasLogic.FLAG_NO_ESCAPE)
|
|
525
524
|
|
|
@@ -527,7 +526,7 @@ class OperandIN(OperandNE):
|
|
|
527
526
|
|
|
528
527
|
class OperandNotIN(OperandNE):
|
|
529
528
|
def __init__(self, column, value):
|
|
530
|
-
if not isinstance(value,
|
|
529
|
+
if not isinstance(value, str):
|
|
531
530
|
value = u"('%s')" % (u"', '".join([ ensure_text(x).replace("'", "''") for x in value]))
|
|
532
531
|
Operand.__init__(self, column, 'NOT IN', value, _HasLogic.LOGIC_NONE, _HasLogic.FLAG_NO_ESCAPE)
|
|
533
532
|
|
|
@@ -594,6 +593,7 @@ class Expression(_HasLogic):
|
|
|
594
593
|
e.logic_op = self.logic_op
|
|
595
594
|
for child in self.children:
|
|
596
595
|
e.children.append(child.copy())
|
|
596
|
+
child.parent = e
|
|
597
597
|
return e
|
|
598
598
|
|
|
599
599
|
def append(self, operand, logic_op):
|
|
@@ -623,8 +623,8 @@ class Expression(_HasLogic):
|
|
|
623
623
|
if self.children[index + 1].logic_op & _HasLogic.LOGIC_NOT:
|
|
624
624
|
op += ' NOT'
|
|
625
625
|
else:
|
|
626
|
-
if (len(self.children) == 1) and (self.children[-1].logic_op & _HasLogic.LOGIC_NOT):
|
|
627
|
-
|
|
626
|
+
# if (len(self.children) == 1) and (self.children[-1].logic_op & _HasLogic.LOGIC_NOT):
|
|
627
|
+
# l[-1].append(True)
|
|
628
628
|
op = None
|
|
629
629
|
l.append(op)
|
|
630
630
|
return l
|
|
@@ -645,7 +645,7 @@ class Expression(_HasLogic):
|
|
|
645
645
|
def __hash__(self):
|
|
646
646
|
return hash(str(self))
|
|
647
647
|
|
|
648
|
-
def
|
|
648
|
+
def __str__(self):
|
|
649
649
|
s = u''
|
|
650
650
|
for child in self.children:
|
|
651
651
|
if child.logic_op & _HasLogic.LOGIC_NOT:
|
|
@@ -657,12 +657,6 @@ class Expression(_HasLogic):
|
|
|
657
657
|
elif child.logic_op & _HasLogic.LOGIC_OR:
|
|
658
658
|
s += ' OR '
|
|
659
659
|
return ensure_text(s)
|
|
660
|
-
|
|
661
|
-
def __str__(self):
|
|
662
|
-
if PY3:
|
|
663
|
-
return self.__unicode__()
|
|
664
|
-
else:
|
|
665
|
-
return self.__unicode__().encode('utf-8')
|
|
666
660
|
|
|
667
661
|
def __repr__(self):
|
|
668
662
|
return str(self)
|
|
@@ -789,7 +783,7 @@ def NOT(arg):
|
|
|
789
783
|
def where(expr):
|
|
790
784
|
if expr is None:
|
|
791
785
|
return []
|
|
792
|
-
elif isinstance(expr,
|
|
786
|
+
elif isinstance(expr, str):
|
|
793
787
|
return where(parse(expr))
|
|
794
788
|
elif isinstance(expr, Operand):
|
|
795
789
|
return [ expr.as_list(), None ]
|
|
@@ -804,10 +798,10 @@ def loads(xml):
|
|
|
804
798
|
if not xml:
|
|
805
799
|
return None
|
|
806
800
|
document = ET.ElementTree()
|
|
807
|
-
if isinstance(xml,
|
|
801
|
+
if isinstance(xml, str):
|
|
808
802
|
xml = ensure_text(xml).encode('utf-8')
|
|
809
|
-
if isinstance(xml,
|
|
810
|
-
xml = io.BytesIO(
|
|
803
|
+
if isinstance(xml, bytes):
|
|
804
|
+
xml = io.BytesIO(xml)
|
|
811
805
|
if not ET.iselement(xml):
|
|
812
806
|
xml = document.parse(xml, ET.XMLTreeBuilder(parse_comments=False))
|
|
813
807
|
if xml.tag == 'operand':
|
kongalib/json.py
CHANGED
|
@@ -16,7 +16,6 @@
|
|
|
16
16
|
from __future__ import print_function
|
|
17
17
|
|
|
18
18
|
from kongalib import JSONEncoder, JSONDecoder, Decimal
|
|
19
|
-
from .compat import *
|
|
20
19
|
|
|
21
20
|
|
|
22
21
|
|
|
@@ -64,7 +63,7 @@ class Decoder(JSONDecoder):
|
|
|
64
63
|
self.stack = [ [None, None] ]
|
|
65
64
|
self.top = None
|
|
66
65
|
|
|
67
|
-
if isinstance(text,
|
|
66
|
+
if isinstance(text, (str, bytes)):
|
|
68
67
|
self.parse(text)
|
|
69
68
|
else:
|
|
70
69
|
while True:
|
kongalib/scripting.py
CHANGED
|
@@ -16,8 +16,8 @@
|
|
|
16
16
|
from __future__ import print_function
|
|
17
17
|
from __future__ import absolute_import
|
|
18
18
|
|
|
19
|
-
from kongalib import Error
|
|
20
|
-
from
|
|
19
|
+
from kongalib import Error
|
|
20
|
+
from _kongalib import get_application_log_path, set_interpreter_timeout, get_interpreter_timeout, get_interpreter_time_left, _set_process_foreground
|
|
21
21
|
|
|
22
22
|
import sys
|
|
23
23
|
import os
|
|
@@ -148,7 +148,7 @@ def timeout_handler():
|
|
|
148
148
|
|
|
149
149
|
|
|
150
150
|
|
|
151
|
-
def init_interpreter(
|
|
151
|
+
def init_interpreter():
|
|
152
152
|
_State.io.append((sys.stdout, sys.stderr, sys.stdin))
|
|
153
153
|
try:
|
|
154
154
|
proxy._initialize()
|
|
@@ -176,10 +176,7 @@ def init_interpreter(init_logging=True):
|
|
|
176
176
|
return True
|
|
177
177
|
tb = list(filter(do_filter, tb))
|
|
178
178
|
try:
|
|
179
|
-
|
|
180
|
-
proxy.builtin.print_exception(type, value, tb)
|
|
181
|
-
else:
|
|
182
|
-
proxy.builtin.print_exception(type.__name__, str(value), tb)
|
|
179
|
+
proxy.builtin.print_exception(type, value, tb)
|
|
183
180
|
except:
|
|
184
181
|
debug_log('proxy.builtin.print_exception exception:\n%s' % traceback.format_exc())
|
|
185
182
|
sys.excepthook = excepthook
|
|
@@ -226,7 +223,8 @@ class _Controller(threading.Thread):
|
|
|
226
223
|
name = None
|
|
227
224
|
while name != 'exit':
|
|
228
225
|
try:
|
|
229
|
-
|
|
226
|
+
ready = multiprocessing.connection.wait([ self.conn ], 0.5)
|
|
227
|
+
if not ready:
|
|
230
228
|
if self.request == _Controller.QUIT_REQUEST:
|
|
231
229
|
break
|
|
232
230
|
continue
|
|
@@ -281,16 +279,15 @@ class _Controller(threading.Thread):
|
|
|
281
279
|
|
|
282
280
|
|
|
283
281
|
|
|
284
|
-
def _trampoline(conn, sem, foreground, dll_paths, queue):
|
|
282
|
+
def _trampoline(conn, sem, foreground, env, dll_paths, queue, level):
|
|
283
|
+
logging.getLogger().setLevel(level)
|
|
285
284
|
logger = logging.getLogger('script._trampoline')
|
|
286
285
|
handler = logging.handlers.QueueHandler(queue)
|
|
287
|
-
handler.setLevel(
|
|
286
|
+
handler.setLevel(level)
|
|
288
287
|
logger.addHandler(handler)
|
|
289
|
-
logger.setLevel(logging.DEBUG)
|
|
290
288
|
logger.debug('entering interpreter process')
|
|
291
289
|
try:
|
|
292
|
-
|
|
293
|
-
_set_process_foreground()
|
|
290
|
+
_set_process_foreground(foreground)
|
|
294
291
|
for path in dll_paths:
|
|
295
292
|
try:
|
|
296
293
|
os.add_dll_directory(path)
|
|
@@ -298,6 +295,11 @@ def _trampoline(conn, sem, foreground, dll_paths, queue):
|
|
|
298
295
|
except:
|
|
299
296
|
if sys.platform == 'win32':
|
|
300
297
|
logger.error('error adding DLL directory: %s' % path)
|
|
298
|
+
for key, value in (env or {}).items():
|
|
299
|
+
key = str(key)
|
|
300
|
+
value = str(value)
|
|
301
|
+
os.environ[key] = value
|
|
302
|
+
logger.debug('added env variable %s=%s' % (key, value))
|
|
301
303
|
|
|
302
304
|
_State.controller = _Controller(conn, sem)
|
|
303
305
|
_State.controller.start()
|
|
@@ -309,8 +311,6 @@ def _trampoline(conn, sem, foreground, dll_paths, queue):
|
|
|
309
311
|
args, path, timeout, script, cwd = request
|
|
310
312
|
sys.argv = args
|
|
311
313
|
sys.path = path
|
|
312
|
-
if (not PY3) and isinstance(script, unicode):
|
|
313
|
-
script = script.encode('utf-8', 'replace')
|
|
314
314
|
filename = args[0]
|
|
315
315
|
if cwd:
|
|
316
316
|
os.chdir(cwd)
|
|
@@ -337,6 +337,8 @@ def _trampoline(conn, sem, foreground, dll_paths, queue):
|
|
|
337
337
|
except:
|
|
338
338
|
pass
|
|
339
339
|
_State.controller.join()
|
|
340
|
+
except KeyboardInterrupt:
|
|
341
|
+
logger.debug('user issued a keyboard interrupt')
|
|
340
342
|
except Exception as e:
|
|
341
343
|
import traceback
|
|
342
344
|
logger.critical('unhandled error in interpreter process: %s' % traceback.format_exc())
|
|
@@ -361,7 +363,7 @@ class _ControllerProxy(Proxy):
|
|
|
361
363
|
|
|
362
364
|
|
|
363
365
|
class Interpreter(object):
|
|
364
|
-
def __init__(self, foreground=True):
|
|
366
|
+
def __init__(self, foreground=True, env=None):
|
|
365
367
|
self.proc = None
|
|
366
368
|
self.exc_info = None
|
|
367
369
|
self.conn = None
|
|
@@ -370,7 +372,8 @@ class Interpreter(object):
|
|
|
370
372
|
self.queue = multiprocessing.Queue()
|
|
371
373
|
self.proxy = None
|
|
372
374
|
self.foreground = foreground
|
|
373
|
-
self.
|
|
375
|
+
self.env = env
|
|
376
|
+
self.logger_listener = logging.handlers.QueueListener(self.queue, *logging.getLogger().handlers, respect_handler_level=True)
|
|
374
377
|
|
|
375
378
|
def __del__(self):
|
|
376
379
|
with self.lock:
|
|
@@ -391,7 +394,7 @@ class Interpreter(object):
|
|
|
391
394
|
self.conn, self.client_conn = multiprocessing.Pipe()
|
|
392
395
|
self.proxy = _ControllerProxy(self.conn).controller
|
|
393
396
|
self.logger_listener.start()
|
|
394
|
-
self.proc = multiprocessing.Process(target=_trampoline, args=(self.client_conn, self.sem, self.foreground, _DLL_PATHS, self.queue), daemon=True)
|
|
397
|
+
self.proc = multiprocessing.Process(target=_trampoline, args=(self.client_conn, self.sem, self.foreground, self.env, _DLL_PATHS, self.queue, logging.getLogger().level), daemon=True)
|
|
395
398
|
self.proc.start()
|
|
396
399
|
exitcode = self.proc.exitcode
|
|
397
400
|
if exitcode is not None:
|
|
@@ -431,7 +434,10 @@ class Interpreter(object):
|
|
|
431
434
|
self.proc = None
|
|
432
435
|
self.lock.release()
|
|
433
436
|
try:
|
|
434
|
-
|
|
437
|
+
try:
|
|
438
|
+
proc.terminate()
|
|
439
|
+
except:
|
|
440
|
+
pass
|
|
435
441
|
proc.join(3)
|
|
436
442
|
if proc.is_alive():
|
|
437
443
|
try:
|
|
@@ -442,13 +448,18 @@ class Interpreter(object):
|
|
|
442
448
|
self.lock.acquire()
|
|
443
449
|
|
|
444
450
|
def is_running(self):
|
|
445
|
-
|
|
446
|
-
|
|
451
|
+
conn = self.conn
|
|
452
|
+
proc = self.proc
|
|
453
|
+
return (conn is None) or ((proc is not None) and proc.is_alive())
|
|
447
454
|
|
|
448
455
|
def set_timeout(self, timeout=None, restore=False):
|
|
449
456
|
with self.lock:
|
|
450
457
|
if self.proxy is not None:
|
|
451
|
-
|
|
458
|
+
func = self.proxy.set_timeout
|
|
459
|
+
else:
|
|
460
|
+
func = None
|
|
461
|
+
if func is not None:
|
|
462
|
+
return func(timeout, restore)
|
|
452
463
|
|
|
453
464
|
def get_time_left(self):
|
|
454
465
|
with self.lock:
|
|
@@ -518,6 +529,7 @@ class _Method(object):
|
|
|
518
529
|
if DEBUG:
|
|
519
530
|
debug_log('[Proxy] call sent in %f secs. Waiting reply: %s' % (time.time() - s, str((self.handler._name, self.name))))
|
|
520
531
|
|
|
532
|
+
multiprocessing.connection.wait([ self.handler._conn ])
|
|
521
533
|
e, result = self.handler._conn.recv()
|
|
522
534
|
if DEBUG:
|
|
523
535
|
s = time.time()
|
|
@@ -565,7 +577,8 @@ class _ServerProxy(threading.Thread):
|
|
|
565
577
|
self.conn = self.listener.accept()
|
|
566
578
|
debug_log("[ServerProxy] got proxy")
|
|
567
579
|
while True:
|
|
568
|
-
|
|
580
|
+
ready = multiprocessing.connection.wait([ self.conn ], 0.5)
|
|
581
|
+
if ready:
|
|
569
582
|
data = self.conn.recv()
|
|
570
583
|
handler, name, args, kwargs = data
|
|
571
584
|
if handler in self.handlers:
|
|
@@ -726,6 +739,7 @@ def execute(script=None, filename=None, argv=None, path=None, timeout=0, handler
|
|
|
726
739
|
else:
|
|
727
740
|
debug_log("[ServerProxy] unhandled execute exception: %s" % traceback.format_exc())
|
|
728
741
|
type, value, tb = sys.exc_info()
|
|
742
|
+
tb = traceback.format_tb(tb)
|
|
729
743
|
def do_filter(entry):
|
|
730
744
|
filename = entry[0].replace('\\', '/')
|
|
731
745
|
if filename.endswith('kongalib/scripting.py') or filename.endswith('__script_host__.py'):
|
|
@@ -733,10 +747,7 @@ def execute(script=None, filename=None, argv=None, path=None, timeout=0, handler
|
|
|
733
747
|
return True
|
|
734
748
|
tb = list(filter(do_filter, tb))
|
|
735
749
|
try:
|
|
736
|
-
|
|
737
|
-
_handlers['builtin'].print_exception(type, value, tb)
|
|
738
|
-
else:
|
|
739
|
-
_handlers['builtin'].print_exception(type.__name__, str(value), tb)
|
|
750
|
+
_handlers['builtin'].print_exception(type, value, tb)
|
|
740
751
|
except:
|
|
741
752
|
debug_log('proxy.builtin.print_exception exception:\n%s' % traceback.format_exc())
|
|
742
753
|
finally:
|
|
@@ -1,36 +1,42 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: kongalib
|
|
3
|
-
Version:
|
|
3
|
+
Version: 2.0.0.post1
|
|
4
4
|
Summary: Konga client library
|
|
5
|
-
|
|
6
|
-
Author: EasyByte Software
|
|
7
|
-
Author-email: konga@easybyte.it
|
|
5
|
+
Author-email: EasyByte Software <konga@easybyte.it>
|
|
8
6
|
License: LGPL
|
|
7
|
+
Project-URL: homepage, https://github.com/easybyte-software/kongalib
|
|
8
|
+
Project-URL: documentation, https://public.easybyte.it/docs/current/technical/kongalib/index.html
|
|
9
|
+
Project-URL: repository, https://github.com/easybyte-software/kongalib.git
|
|
9
10
|
Keywords: konga,client,erp
|
|
10
11
|
Classifier: Natural Language :: Italian
|
|
11
12
|
Classifier: Programming Language :: Python
|
|
12
|
-
Classifier: Programming Language :: Python :: 2
|
|
13
|
-
Classifier: Programming Language :: Python :: 2.7
|
|
14
13
|
Classifier: Programming Language :: Python :: 3
|
|
15
|
-
Classifier: Programming Language :: Python :: 3
|
|
16
|
-
Classifier: Programming Language :: Python :: 3.7
|
|
14
|
+
Classifier: Programming Language :: Python :: 3 :: Only
|
|
17
15
|
Classifier: Programming Language :: Python :: 3.8
|
|
18
16
|
Classifier: Programming Language :: Python :: 3.9
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.10
|
|
18
|
+
Classifier: Programming Language :: Python :: 3.11
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Programming Language :: Python :: 3.13
|
|
21
|
+
Classifier: Programming Language :: Python :: 3.14
|
|
19
22
|
Classifier: Programming Language :: C++
|
|
20
23
|
Classifier: Development Status :: 5 - Production/Stable
|
|
21
24
|
Classifier: Environment :: Console
|
|
22
25
|
Classifier: Intended Audience :: Developers
|
|
23
26
|
Classifier: Intended Audience :: Information Technology
|
|
24
27
|
Classifier: Intended Audience :: Financial and Insurance Industry
|
|
25
|
-
Classifier: License :: OSI Approved :: GNU Lesser General Public License v3 (LGPLv3)
|
|
26
28
|
Classifier: Operating System :: MacOS :: MacOS X
|
|
27
29
|
Classifier: Operating System :: Microsoft :: Windows
|
|
28
30
|
Classifier: Operating System :: POSIX :: Linux
|
|
29
31
|
Classifier: Topic :: Office/Business
|
|
30
32
|
Classifier: Topic :: Office/Business :: Financial
|
|
31
33
|
Classifier: Topic :: Software Development :: Libraries
|
|
34
|
+
Requires-Python: >=3.8
|
|
35
|
+
Description-Content-Type: text/x-rst
|
|
32
36
|
License-File: LICENSE
|
|
33
37
|
Requires-Dist: colorama
|
|
38
|
+
Requires-Dist: nest_asyncio
|
|
39
|
+
Dynamic: license-file
|
|
34
40
|
|
|
35
41
|
Kongalib
|
|
36
42
|
========
|
|
@@ -44,9 +50,9 @@ Kongalib
|
|
|
44
50
|
.. image:: https://img.shields.io/badge/License-LGPLv3-blue.svg
|
|
45
51
|
:alt: LGPL v3 License
|
|
46
52
|
:target: https://www.gnu.org/licenses/lgpl-3.0.en.html
|
|
47
|
-
.. image:: https://
|
|
53
|
+
.. image:: https://github.com/easybyte-software/kongalib/actions/workflows/build_wheels.yml/badge.svg?event=workflow_dispatch
|
|
48
54
|
:alt: Build Status
|
|
49
|
-
:target: https://
|
|
55
|
+
:target: https://github.com/easybyte-software/kongalib/actions/workflows/build_wheels.yml
|
|
50
56
|
|
|
51
57
|
Libreria Python di comunicazione con i server `EasyByte Konga`_. Tramite
|
|
52
58
|
*kongalib* è possibile connettersi ad un server Konga (integrato in Konga Pro o
|
|
@@ -73,16 +79,16 @@ Se si desidera è possibile compilare i sorgenti. I prerequisiti per compilare
|
|
|
73
79
|
|
|
74
80
|
**Windows**
|
|
75
81
|
|
|
76
|
-
Sono supportate le versioni di Windows dalla
|
|
82
|
+
Sono supportate le versioni di Windows dalla 10 in su. Come prerequisiti è
|
|
77
83
|
necessario installare:
|
|
78
84
|
|
|
79
|
-
- Microsoft Visual Studio 2017
|
|
85
|
+
- Microsoft Visual Studio 2017 o successiva
|
|
80
86
|
- `SDK di Konga`_
|
|
81
87
|
|
|
82
88
|
|
|
83
89
|
**MacOS X**
|
|
84
90
|
|
|
85
|
-
Sono supportate le versioni di macOS dalla 10.
|
|
91
|
+
Sono supportate le versioni di macOS dalla 10.9 in su. Come prerequisiti è
|
|
86
92
|
necessario installare:
|
|
87
93
|
|
|
88
94
|
- XCode (assicurarsi di aver installato anche i tool da linea di comando)
|
|
@@ -92,9 +98,9 @@ necessario installare:
|
|
|
92
98
|
**Linux**
|
|
93
99
|
|
|
94
100
|
Benchè il pacchetto binario wheel per Linux supporti tutte le distribuzioni
|
|
95
|
-
Linux moderne (specifica `
|
|
101
|
+
Linux moderne (specifica `manylinux_2_28`_), al momento la compilazione da parte di
|
|
96
102
|
terzi è supportata ufficialmente solo se si usa una distribuzione Linux basata su
|
|
97
|
-
Debian, in particolare Ubuntu Linux dalla versione
|
|
103
|
+
Debian, in particolare Ubuntu Linux dalla versione 20.04 in su. Sono necessari i
|
|
98
104
|
seguenti pacchetti *deb*:
|
|
99
105
|
|
|
100
106
|
- build-essential
|
|
@@ -102,18 +108,15 @@ seguenti pacchetti *deb*:
|
|
|
102
108
|
- python-dev
|
|
103
109
|
- `easybyte-konga-dev`_
|
|
104
110
|
|
|
105
|
-
La compilazione
|
|
111
|
+
La compilazione come da standard Python è possibile sempre tramite *pip*, eseguendo
|
|
112
|
+
dalla directory dei sorgenti::
|
|
106
113
|
|
|
107
|
-
|
|
114
|
+
pip install .
|
|
108
115
|
|
|
109
116
|
|
|
110
117
|
.. note:: Sotto piattaforma Windows per la corretta compilazione è necessario
|
|
111
|
-
impostare la variabile d'ambiente `KONGASDK`
|
|
112
|
-
dell'`SDK di Konga`_.
|
|
113
|
-
Visual Studio 2017 e non è compatibile con Python 2.x (che sotto Windows
|
|
114
|
-
richiede Visual Studio 2008); se si desidera usare *kongalib* con Python 2.x
|
|
115
|
-
sotto Windows, è necessario usare la *wheel* precompilata installabile
|
|
116
|
-
tramite *pip*.
|
|
118
|
+
impostare la variabile d'ambiente `KONGASDK` alla directory d'installazione
|
|
119
|
+
dell'`SDK di Konga`_.
|
|
117
120
|
|
|
118
121
|
|
|
119
122
|
Risorse
|
|
@@ -143,5 +146,5 @@ Risorse
|
|
|
143
146
|
.. _Script di utilità comune per Konga: https://github.com/easybyte-software/konga_scripts
|
|
144
147
|
.. _SDK di Konga: http://public.easybyte.it/downloads/current
|
|
145
148
|
.. _easybyte-konga-dev: http://public.easybyte.it/downloads/current
|
|
146
|
-
..
|
|
149
|
+
.. _manylinux_2_28: https://github.com/pypa/manylinux
|
|
147
150
|
|
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
_kongalib.cp311-win_amd64.pdb,sha256=jRszejY8QBuoOqG4U2Wfxawq23LhUYS4o7khh-DWsQE,7344128
|
|
2
|
+
_kongalib.cp311-win_amd64.pyd,sha256=BP5_tjH6G1EwmoReYJjnzvxoMYau1gHZkwArtB2x-Qo,2533888
|
|
3
|
+
kongaui.py,sha256=0sSKUsOo5vLNH3wyUUl4icOL4z4CXqoPAR2fqYQZE7o,20598
|
|
4
|
+
kongautil.py,sha256=PSObmHX6kVf54mtIyBXtxzf4CMHUsj_ppDNSWjY3Y2c,24005
|
|
5
|
+
kongalib/__init__.py,sha256=VPFvthIAm7K668_Fxx_4Wf6rwZCAs6dwBz6DfZtwrLU,12979
|
|
6
|
+
kongalib/async_client.py,sha256=XFzkYLr0KbaNvCN3piS-AdWigcFtJqFpcDCN0fUKeMA,48017
|
|
7
|
+
kongalib/client.py,sha256=8fz5L0mvRa5q0G06gK1MEN0_PYapIgkMK_wd1_Yrexo,58834
|
|
8
|
+
kongalib/constants.py,sha256=r59fg2-CCTWRvKOusxXe9FTBrSAmFt5Esn70DsyEn8s,8793
|
|
9
|
+
kongalib/data_dictionary.py,sha256=a-_aTlZeJPGkxkxzG040A2yrfXf_Stup3CTurh_93B0,11298
|
|
10
|
+
kongalib/db.py,sha256=qnSon_7N5Po0-ww-88mL7DZlGX7_ASIM4tMY9bGGBnk,8354
|
|
11
|
+
kongalib/expression.py,sha256=A7-erKQPF4VroB3ERCTvLYyOv5_gm1a-rxToLNhd8VY,21230
|
|
12
|
+
kongalib/json.py,sha256=-8h3e92hLzsElxZhLgpcoQWfakSYyY0i7vsxB7Z7qtk,2341
|
|
13
|
+
kongalib/lex.py,sha256=tV9VGF97XHRFf0eBICVzTILzH878i_slXLsoktFnZTQ,41797
|
|
14
|
+
kongalib/scripting.py,sha256=153S5jtpLie_LztS6FH1QLs1-yrWVCdWM7hzY8FWp6g,20344
|
|
15
|
+
kongalib/yacc.py,sha256=UHnHKzBknH7qzIT7xJFIHYKBTzOIxWILtGPdSI29XcE,131768
|
|
16
|
+
kongalib-2.0.0.post1.dist-info/licenses/LICENSE,sha256=LPNKwDiu5awG-TPd0dqYJuC7k4PBPY4LCI_O0LSpW1s,7814
|
|
17
|
+
kongalib-2.0.0.post1.dist-info/METADATA,sha256=XUhKmSxS4lqMe0PuaQlZFt-qAjZenn0O7Jebn3iBsVE,5408
|
|
18
|
+
kongalib-2.0.0.post1.dist-info/WHEEL,sha256=JLOMsP7F5qtkAkINx5UnzbFguf8CqZeraV8o04b0I8I,101
|
|
19
|
+
kongalib-2.0.0.post1.dist-info/top_level.txt,sha256=htHdvBd1NQjLXNwXgTzCMPtyfCtorpw6jUZzu09vDYY,37
|
|
20
|
+
kongalib-2.0.0.post1.dist-info/zip-safe,sha256=frcCV1k9oG9oKj3dpUqdJg1PxRT2RSN_XKdLCPjaYaY,2
|
|
21
|
+
kongalib-2.0.0.post1.dist-info/RECORD,,
|
kongaui.py
CHANGED
|
@@ -28,14 +28,6 @@ import kongautil
|
|
|
28
28
|
from kongalib.scripting import _TimeoutBlocker
|
|
29
29
|
from kongalib.scripting import proxy as _proxy
|
|
30
30
|
|
|
31
|
-
PY3 = (sys.version_info[0] >= 3)
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
if PY3:
|
|
35
|
-
basestring = str
|
|
36
|
-
else:
|
|
37
|
-
input = raw_input
|
|
38
|
-
|
|
39
31
|
|
|
40
32
|
|
|
41
33
|
BUTTON_OK = 0x0001 #: Bottone "Ok"
|
|
@@ -75,47 +67,8 @@ if not _proxy.is_valid():
|
|
|
75
67
|
|
|
76
68
|
|
|
77
69
|
def _get_term_width():
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
return shutil.get_terminal_size(fallback=(80, 24))[0]
|
|
81
|
-
else:
|
|
82
|
-
# from https://stackoverflow.com/questions/566746/how-to-get-linux-console-window-width-in-python
|
|
83
|
-
if sys.platform == 'win32':
|
|
84
|
-
try:
|
|
85
|
-
from ctypes import windll, create_string_buffer
|
|
86
|
-
h = windll.kernel32.GetStdHandle(-12)
|
|
87
|
-
csbi = create_string_buffer(22)
|
|
88
|
-
res = windll.kernel32.GetConsoleScreenBufferInfo(h, csbi)
|
|
89
|
-
except:
|
|
90
|
-
res = None
|
|
91
|
-
if res:
|
|
92
|
-
import struct
|
|
93
|
-
(bufx, bufy, curx, cury, wattr, left, top, right, bottom, maxx, maxy) = struct.unpack("hhhhHhhhhhh", csbi.raw)
|
|
94
|
-
return right - left + 1
|
|
95
|
-
else:
|
|
96
|
-
return 80
|
|
97
|
-
else:
|
|
98
|
-
def ioctl_GWINSZ(fd):
|
|
99
|
-
try:
|
|
100
|
-
import fcntl, termios, struct
|
|
101
|
-
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ, '1234'))
|
|
102
|
-
except:
|
|
103
|
-
return None
|
|
104
|
-
return cr
|
|
105
|
-
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
|
|
106
|
-
if not cr:
|
|
107
|
-
try:
|
|
108
|
-
fd = os.open(os.ctermid(), os.O_RDONLY)
|
|
109
|
-
cr = ioctl_GWINSZ(fd)
|
|
110
|
-
os.close(fd)
|
|
111
|
-
except:
|
|
112
|
-
pass
|
|
113
|
-
if not cr:
|
|
114
|
-
try:
|
|
115
|
-
cr = (env['LINES'], env['COLUMNS'])
|
|
116
|
-
except:
|
|
117
|
-
return 80
|
|
118
|
-
return int(cr[1])
|
|
70
|
+
import shutil
|
|
71
|
+
return shutil.get_terminal_size(fallback=(80, 24))[0]
|
|
119
72
|
|
|
120
73
|
|
|
121
74
|
|
|
@@ -338,11 +291,7 @@ def set_progress(progress=None, message=None, state=None):
|
|
|
338
291
|
tick = ('\\', '|', '/', '-')[int(time.time() * 5) % 4]
|
|
339
292
|
bar = '%s %s' % (elide(', '.join(text), term_width - 3), tick)
|
|
340
293
|
else:
|
|
341
|
-
|
|
342
|
-
block = u'\u2588'
|
|
343
|
-
else:
|
|
344
|
-
block = '#'
|
|
345
|
-
progress = (block * int((progress * 30) // 100))
|
|
294
|
+
progress = ('\u2588' * int((progress * 30) // 100))
|
|
346
295
|
bar = '|%-30s| %s' % (progress, elide(', '.join(text), term_width - 34))
|
|
347
296
|
print('\033[2K\r' + bar, end='')
|
|
348
297
|
sys.stdout.flush()
|
|
@@ -494,7 +443,7 @@ def execute_form(form_data, title=None, message=None, condition=None):
|
|
|
494
443
|
raise InvalidInput('Expected iso date (YYYY-MM-DD)')
|
|
495
444
|
elif wtype in ('choice', 'listbox', 'combobox'):
|
|
496
445
|
items = entry.get('items', [])
|
|
497
|
-
if (not isinstance(items, (tuple, list))) or (not all([ isinstance(item,
|
|
446
|
+
if (not isinstance(items, (tuple, list))) or (not all([ isinstance(item, str) for item in items ])):
|
|
498
447
|
raise RuntimeError("Expected list of strings as 'items' value")
|
|
499
448
|
print(label)
|
|
500
449
|
for index, item in enumerate(items):
|