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.
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
+