kongalib 2.0.4__cp314-cp314t-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-314t-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
kongalib/db.py
ADDED
|
@@ -0,0 +1,267 @@
|
|
|
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
|
+
import time
|
|
17
|
+
import datetime
|
|
18
|
+
|
|
19
|
+
from kongalib import Client, Decimal, Error as _Error, ErrorList
|
|
20
|
+
from .constants import *
|
|
21
|
+
|
|
22
|
+
|
|
23
|
+
apilevel = "2.0" #: Versione delle API, come da specifica
|
|
24
|
+
threadsafety = 2 #: E' possibile usare le funzioni di modulo e gli oggetti :class:`.Connection` da thread diversi
|
|
25
|
+
paramstyle = "format" #: Il formato dei parametri nelle query deve essere nello stile printf (WHERE name=%s)
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
class Error(Exception):
|
|
29
|
+
"""Eccezione base, come da specifica."""
|
|
30
|
+
def __init__(self, msg):
|
|
31
|
+
self.msg = msg
|
|
32
|
+
def __str__(self):
|
|
33
|
+
return self.msg
|
|
34
|
+
|
|
35
|
+
class Warning(Exception):
|
|
36
|
+
pass
|
|
37
|
+
|
|
38
|
+
class InterfaceError(Error):
|
|
39
|
+
pass
|
|
40
|
+
|
|
41
|
+
class DatabaseError(Error):
|
|
42
|
+
pass
|
|
43
|
+
|
|
44
|
+
class InternalError(DatabaseError):
|
|
45
|
+
"""Errore interno."""
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
class OperationalError(DatabaseError):
|
|
49
|
+
"""Eccezione che viene lanciata su errori di connessione e/o comunicazione con il server Konga."""
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
class ProgrammingError(DatabaseError):
|
|
53
|
+
"""Eccezione che viene lanciata se l'esecuzione di una query SQL ha generato un errore."""
|
|
54
|
+
pass
|
|
55
|
+
|
|
56
|
+
class IntegrityError(DatabaseError):
|
|
57
|
+
pass
|
|
58
|
+
|
|
59
|
+
class DataError(DatabaseError):
|
|
60
|
+
pass
|
|
61
|
+
|
|
62
|
+
class NotSupportedError(DatabaseError):
|
|
63
|
+
pass
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
class STRING(object):
|
|
67
|
+
def __init__(self, string):
|
|
68
|
+
self.string = string
|
|
69
|
+
|
|
70
|
+
class BINARY(object):
|
|
71
|
+
def __init__(self, binary):
|
|
72
|
+
self.binary = binary
|
|
73
|
+
|
|
74
|
+
class NUMBER(object):
|
|
75
|
+
def __init__(self, number):
|
|
76
|
+
self.number = number
|
|
77
|
+
|
|
78
|
+
class DATETIME(object):
|
|
79
|
+
def __init__(self, datetime):
|
|
80
|
+
self.datetime = datetime
|
|
81
|
+
|
|
82
|
+
class ROWID(object):
|
|
83
|
+
pass
|
|
84
|
+
|
|
85
|
+
|
|
86
|
+
class Connection(Client):
|
|
87
|
+
"""Classe che gestisce una connessione ad un server Konga. Viene usata per instanziare oggetti :class:`.Cursor` su cui poi operare, oppure
|
|
88
|
+
per gestire le transazioni.
|
|
89
|
+
"""
|
|
90
|
+
def close(self):
|
|
91
|
+
"""Chiude la connessione con il server Konga."""
|
|
92
|
+
self.disconnect()
|
|
93
|
+
|
|
94
|
+
def commit(self):
|
|
95
|
+
"""Esegue una ``COMMIT`` per la transazione SQL corrente."""
|
|
96
|
+
self.query("COMMIT")
|
|
97
|
+
|
|
98
|
+
def rollback(self):
|
|
99
|
+
"""Esegue una ``ROLLBACK`` per la transazione SQL corrente."""
|
|
100
|
+
self.query("ROLLBACK")
|
|
101
|
+
|
|
102
|
+
def cursor(self):
|
|
103
|
+
"""Crea un nuovo oggetto :class:`Cursor` associato a questa connessione."""
|
|
104
|
+
return Cursor(self)
|
|
105
|
+
|
|
106
|
+
|
|
107
|
+
class Cursor(object):
|
|
108
|
+
"""Questa classe permette di eseguire query SQL sulla connessione *conn* ad essa associata. Per instanziare oggetti di classe :class:`Cursor`
|
|
109
|
+
si usa il metodo :meth:`.Connection.cursor`.
|
|
110
|
+
La classe può essere anche usato come iteratore; in tal caso per ogni ciclo verrà restituita la prossima riga del result set derivante
|
|
111
|
+
dall'ultima query eseguita sul cursore stesso.
|
|
112
|
+
"""
|
|
113
|
+
def __init__(self, conn):
|
|
114
|
+
self.__connection = conn
|
|
115
|
+
self.__description = None
|
|
116
|
+
self.__rowcount = -1
|
|
117
|
+
self.__rownumber = 0
|
|
118
|
+
self.__arraysize = 1
|
|
119
|
+
self.__result = None
|
|
120
|
+
self.__valid = True
|
|
121
|
+
|
|
122
|
+
def close(self):
|
|
123
|
+
"""Termina l'utilizzo di questo cursore; chiamate successive ai metodi di questo oggetto lanceranno un eccezione di tipo :exc:`.InternalError`."""
|
|
124
|
+
self.__valid = False
|
|
125
|
+
|
|
126
|
+
def execute(self, command, *args):
|
|
127
|
+
"""Esegue la query SQL *command* sulla connessione associata al cursore; *command* può essere nel formato printf, e in tal caso
|
|
128
|
+
*args* sono gli argomenti che vengono sostituiti nella stringa di formato.
|
|
129
|
+
"""
|
|
130
|
+
if not self.__valid:
|
|
131
|
+
raise InternalError('cursor is not valid anymore')
|
|
132
|
+
try:
|
|
133
|
+
self.__rowcount, fields, self.__result = self.__connection.query(command % args)
|
|
134
|
+
except _Error as e:
|
|
135
|
+
if e.errno in (NOT_CONNECTED, CONNECTION_LOST, TIMED_OUT, BAD_REPLY):
|
|
136
|
+
raise OperationalError(str(e))
|
|
137
|
+
else:
|
|
138
|
+
raise ProgrammingError(str(e))
|
|
139
|
+
if len(self.__result) > 0:
|
|
140
|
+
self.__rowcount = len(self.__result)
|
|
141
|
+
self.__description = []
|
|
142
|
+
row = self.__result[0]
|
|
143
|
+
for field, data in zip(fields, row):
|
|
144
|
+
if isinstance(data, (int, float, Decimal)):
|
|
145
|
+
t = NUMBER
|
|
146
|
+
elif isinstance(data, (datetime.date, datetime.datetime)):
|
|
147
|
+
t = DATETIME
|
|
148
|
+
elif isinstance(data, str):
|
|
149
|
+
t = STRING
|
|
150
|
+
else:
|
|
151
|
+
t = BINARY
|
|
152
|
+
self.__description.append((field, t, None, None, None, None, None))
|
|
153
|
+
self.__rownumber = 0
|
|
154
|
+
else:
|
|
155
|
+
self.__result = None
|
|
156
|
+
self.__description = None
|
|
157
|
+
self.__rownumber = None
|
|
158
|
+
|
|
159
|
+
def executemany(self, operation, seq):
|
|
160
|
+
"""Esegue la stessa query SQL tante volte quanta la lunghezza della sequenza *seq*; l'elemento *N* di *seq* deve essere una tupla
|
|
161
|
+
di argomenti da passare come *args* al metodo :meth:`execute` per eseguire la query *N*-esima.
|
|
162
|
+
"""
|
|
163
|
+
for args in seq:
|
|
164
|
+
self.execute(operation, *tuple(args))
|
|
165
|
+
|
|
166
|
+
def fetchone(self):
|
|
167
|
+
"""Restituisce la prossima riga del result set ottenuto dall'ultima query eseguita su questo cursore. La riga è restituita sotto forma di
|
|
168
|
+
tupla di valori."""
|
|
169
|
+
if self.__result is None:
|
|
170
|
+
raise InternalError('no valid result set')
|
|
171
|
+
if self.__rownumber >= len(self.__result):
|
|
172
|
+
return None
|
|
173
|
+
self.__rownumber += 1
|
|
174
|
+
return tuple(self.__result[self.__rownumber - 1])
|
|
175
|
+
|
|
176
|
+
def fetchmany(self, size=None):
|
|
177
|
+
"""Restituisce una lista di righe in cui ogni riga è nello stesso formato restituito da :meth:`fetchone`. La lista includerà al massimo
|
|
178
|
+
*size* righe; se *size* è ``None``, verranno incluse al massimo :attr:`arraysize` righe.
|
|
179
|
+
"""
|
|
180
|
+
if size is None:
|
|
181
|
+
size = self.__arraysize
|
|
182
|
+
result = []
|
|
183
|
+
for c in range(0, size):
|
|
184
|
+
result.append(self.fetchone())
|
|
185
|
+
return result
|
|
186
|
+
|
|
187
|
+
def fetchall(self):
|
|
188
|
+
"""Restituisce tutte le righe del result set corrente."""
|
|
189
|
+
size = len(self.__result or []) - (self.__rownumber or 0)
|
|
190
|
+
return self.fetchmany(size)
|
|
191
|
+
|
|
192
|
+
def __iter__(self):
|
|
193
|
+
return self
|
|
194
|
+
|
|
195
|
+
def __next__(self):
|
|
196
|
+
row = self.fetchone()
|
|
197
|
+
if row is None:
|
|
198
|
+
raise StopIteration
|
|
199
|
+
return row
|
|
200
|
+
|
|
201
|
+
def next(self):
|
|
202
|
+
return self.__next__()
|
|
203
|
+
|
|
204
|
+
def setinputsizes(self, sizes):
|
|
205
|
+
pass
|
|
206
|
+
|
|
207
|
+
def setoutputsize(self, size, column):
|
|
208
|
+
pass
|
|
209
|
+
|
|
210
|
+
@property
|
|
211
|
+
def connection(self):
|
|
212
|
+
"""Proprietà in sola lettura che restituisce l'oggetto :class:`Connection` associato a questo cursore."""
|
|
213
|
+
return self.__connection
|
|
214
|
+
|
|
215
|
+
@property
|
|
216
|
+
def rowcount(self):
|
|
217
|
+
"""Proprietà in sola lettura che restituisce il numero di righe del result set corrente."""
|
|
218
|
+
return self.__rowcount
|
|
219
|
+
|
|
220
|
+
@property
|
|
221
|
+
def rownumber(self):
|
|
222
|
+
"""Proprietà in sola lettura che restituisce il numero di riga corrente all'interno del result set."""
|
|
223
|
+
return self.__rownumber
|
|
224
|
+
|
|
225
|
+
@property
|
|
226
|
+
def arraysize(self):
|
|
227
|
+
"""Proprietà in lettura/scrittura che specifica il numero massimo di righe da includere nel risultato di :meth:`fetchmany` se *size* è ``None``."""
|
|
228
|
+
return self.__arraysize
|
|
229
|
+
|
|
230
|
+
@arraysize.setter
|
|
231
|
+
def arraysize(self, size):
|
|
232
|
+
self.__arraysize = size
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
def Date(year, month, day):
|
|
236
|
+
return datetime.date(year, month, day)
|
|
237
|
+
|
|
238
|
+
def Time(hour, minute, second):
|
|
239
|
+
return datetime.time(hour, minute, second)
|
|
240
|
+
|
|
241
|
+
def Timestamp(year, month, day, hour, minute, second):
|
|
242
|
+
return datetime.datetime(year, month, day, hour, minute, second)
|
|
243
|
+
|
|
244
|
+
def DateFromTicks(ticks):
|
|
245
|
+
return Date(*time.localtime(ticks)[:3])
|
|
246
|
+
|
|
247
|
+
def TimeFromTicks(ticks):
|
|
248
|
+
return Time(*time.localtime(ticks)[3:6])
|
|
249
|
+
|
|
250
|
+
def TimestampFromTicks(ticks):
|
|
251
|
+
return Timestamp(*time.localtime(ticks)[:6])
|
|
252
|
+
|
|
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.
|
|
257
|
+
"""
|
|
258
|
+
conn = Connection()
|
|
259
|
+
try:
|
|
260
|
+
conn.connect({ 'host': host, 'port': port }, options={ 'tenant_key': tenant_key })
|
|
261
|
+
conn.open_database(driver, database)
|
|
262
|
+
conn.authenticate(user, password)
|
|
263
|
+
except _Error as e:
|
|
264
|
+
raise OperationalError(str(e))
|
|
265
|
+
return conn
|
|
266
|
+
|
|
267
|
+
|