Skip to content

Commit 0c05343

Browse files
Add PEP-249 dbapi module (#160)
Implemented dbapi2 interface in dbapi module. See [1] for details. The main motivation for the module creation was the integration Django with Tarantool database through django-tarantool database backend [2] which requires dbapi connector to the database. All the optional extensions and methods were ignored because Django does not require them. Anyway, fell free to suggest its implementation as needed. Unit tests were taken from dbapi-compliance [3] package. Interactive transactions are not currently supported by Tarantool and theirs implementation will be added in the connector when the feature is stable it Tarantool itself. [1] https://www.python.org/dev/peps/pep-0249/ [2] https://github.com/artembo/django-tarantool [3] https://github.com/baztian/dbapi-compliance/ Co-authored-by: Denis Ignatenko <[email protected]>
1 parent 29184e0 commit 0c05343

File tree

5 files changed

+371
-15
lines changed

5 files changed

+371
-15
lines changed

tarantool/__init__.py

+1-1
Original file line numberDiff line numberDiff line change
@@ -75,4 +75,4 @@ def connectmesh(addrs=({'host': 'localhost', 'port': 3301},), user=None,
7575

7676
__all__ = ['connect', 'Connection', 'connectmesh', 'MeshConnection', 'Schema',
7777
'Error', 'DatabaseError', 'NetworkError', 'NetworkWarning',
78-
'SchemaError']
78+
'SchemaError', 'dbapi']

tarantool/connection.py

+25-8
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import msgpack
2020

21-
import tarantool.error
2221
from tarantool.response import Response
2322
from tarantool.request import (
2423
Request,
@@ -50,12 +49,20 @@
5049
ITERATOR_ALL
5150
)
5251
from tarantool.error import (
52+
Error,
5353
NetworkError,
5454
DatabaseError,
5555
InterfaceError,
5656
SchemaError,
5757
NetworkWarning,
58+
OperationalError,
59+
DataError,
60+
IntegrityError,
61+
InternalError,
62+
ProgrammingError,
63+
NotSupportedError,
5864
SchemaReloadException,
65+
Warning,
5966
warn
6067
)
6168
from tarantool.schema import Schema
@@ -77,11 +84,20 @@ class Connection(object):
7784
Also this class provides low-level interface to data manipulation
7885
(insert/delete/update/select).
7986
'''
80-
Error = tarantool.error
87+
# DBAPI Extension: supply exceptions as attributes on the connection
88+
Error = Error
8189
DatabaseError = DatabaseError
8290
InterfaceError = InterfaceError
8391
SchemaError = SchemaError
8492
NetworkError = NetworkError
93+
Warning = Warning
94+
DataError = DataError
95+
OperationalError = OperationalError
96+
IntegrityError = IntegrityError
97+
InternalError = InternalError
98+
ProgrammingError = ProgrammingError
99+
NotSupportedError = NotSupportedError
100+
ImproperlyConfigured = Exception
85101

86102
def __init__(self, host, port,
87103
user=None,
@@ -92,6 +108,7 @@ def __init__(self, host, port,
92108
connect_now=True,
93109
encoding=ENCODING_DEFAULT,
94110
call_16=False,
111+
use_list=True,
95112
connection_timeout=CONNECTION_TIMEOUT):
96113
'''
97114
Initialize a connection to the server.
@@ -124,6 +141,7 @@ def __init__(self, host, port,
124141
self._socket = None
125142
self.connected = False
126143
self.error = True
144+
self.use_list = use_list
127145
self.encoding = encoding
128146
self.call_16 = call_16
129147
self.connection_timeout = connection_timeout
@@ -261,7 +279,7 @@ def _send_request_wo_reconnect(self, request):
261279
while True:
262280
try:
263281
self._socket.sendall(bytes(request))
264-
response = Response(self, self._read_response())
282+
response = Response(self, self._read_response(), self.use_list)
265283
break
266284
except SchemaReloadException as e:
267285
self.update_schema(e.schema_version)
@@ -299,7 +317,6 @@ def check(): # Check that connection is alive
299317
err = ctypes.get_last_error()
300318
self._socket.setblocking(True)
301319

302-
303320
WWSAEWOULDBLOCK = 10035
304321
if (retbytes < 0) and (err == errno.EAGAIN or
305322
err == errno.EWOULDBLOCK or
@@ -446,7 +463,7 @@ def _join_v16(self, server_uuid):
446463
self._socket.sendall(bytes(request))
447464

448465
while True:
449-
resp = Response(self, self._read_response())
466+
resp = Response(self, self._read_response(), self.use_list)
450467
yield resp
451468
if resp.code == REQUEST_TYPE_OK or resp.code >= REQUEST_TYPE_ERROR:
452469
return
@@ -460,7 +477,7 @@ class JoinState:
460477
self._socket.sendall(bytes(request))
461478
state = JoinState.Handshake
462479
while True:
463-
resp = Response(self, self._read_response())
480+
resp = Response(self, self._read_response(), self.use_list)
464481
yield resp
465482
if resp.code >= REQUEST_TYPE_ERROR:
466483
return
@@ -489,7 +506,7 @@ def subscribe(self, cluster_uuid, server_uuid, vclock=None):
489506
request = RequestSubscribe(self, cluster_uuid, server_uuid, vclock)
490507
self._socket.sendall(bytes(request))
491508
while True:
492-
resp = Response(self, self._read_response())
509+
resp = Response(self, self._read_response(), self.use_list)
493510
yield resp
494511
if resp.code >= REQUEST_TYPE_ERROR:
495512
return
@@ -805,4 +822,4 @@ def execute(self, query, params=None):
805822
params = []
806823
request = RequestExecute(self, query, params)
807824
response = self._send_request(request)
808-
return response
825+
return response

0 commit comments

Comments
 (0)