Skip to content
This repository was archived by the owner on Dec 18, 2021. It is now read-only.

Commit 9459d2a

Browse files
committed
Python 3 support
1 parent dce64bc commit 9459d2a

13 files changed

Lines changed: 72 additions & 43 deletions

NEWS.rst

Lines changed: 3 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -4,8 +4,9 @@ Changelog
44
Version 0.5
55
-----------
66

7-
- The driver now uses the Protocol Buffers protocol instead of JSON to communicate with Avatica.
8-
- Dropped support for Phoenix 4.6 and older.
7+
- Added support for Python 3.
8+
- Switched from the JSON serialization to Protocol Buffers, improved compatibility with Phoenix 4.8.
9+
- Phoenix 4.6 and older are no longer supported.
910

1011
Version 0.4
1112
-----------

gen-protobuf.sh

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,8 @@
11
#!/usr/bin/env bash
22

33
export CALCITE_VER=calcite-1.8.0
4-
export CALCITE_DIR=calcite
54

6-
rm -rf phoenixdb/$CALCITE_DIR
5+
rm -rf phoenixdb/calcite
76
rm -rf calcite-tmp
87

98
git init calcite-tmp
@@ -14,9 +13,10 @@ echo "avatica/core/src/main/protobuf/*" >> .git/info/sparse-checkout
1413
git pull --depth=1 origin $CALCITE_VER
1514

1615
cd ..
17-
mkdir -p phoenixdb/$CALCITE_DIR
18-
protoc --proto_path=calcite-tmp/avatica/core/src/main/protobuf/ --python_out=phoenixdb/$CALCITE_DIR calcite-tmp/avatica/core/src/main/protobuf/*.proto
16+
mkdir -p phoenixdb/calcite
17+
protoc --proto_path=calcite-tmp/avatica/core/src/main/protobuf/ --python_out=phoenixdb/calcite calcite-tmp/avatica/core/src/main/protobuf/*.proto
18+
sed -i 's/import common_pb2/from . import common_pb2/' phoenixdb/calcite/*_pb2.py
1919

2020
rm -rf calcite-tmp
2121

22-
echo '' >> phoenixdb/$CALCITE_DIR/__init__.py
22+
echo '' >> phoenixdb/calcite/__init__.py

phoenixdb/avatica.py

Lines changed: 18 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -16,16 +16,28 @@
1616

1717
import re
1818
import socket
19-
import httplib
2019
import pprint
2120
import math
2221
import logging
23-
import urlparse
2422
import time
25-
from HTMLParser import HTMLParser
2623
from phoenixdb import errors
2724
from phoenixdb.calcite import requests_pb2, common_pb2, responses_pb2
2825

26+
try:
27+
import httplib
28+
except ImportError:
29+
import http.client as httplib
30+
31+
try:
32+
import urlparse
33+
except ImportError:
34+
import urllib.parse as urlparse
35+
36+
try:
37+
from HTMLParser import HTMLParser
38+
except ImportError:
39+
from html.parser import HTMLParser
40+
2941
__all__ = ['AvaticaClient']
3042

3143
logger = logging.getLogger(__name__)
@@ -191,7 +203,7 @@ def _apply(self, request_data, expected_response_type=None):
191203

192204
if response.status != httplib.OK:
193205
logger.debug("Received response\n%s", response_body)
194-
if '<html>' in response_body:
206+
if b'<html>' in response_body:
195207
parse_error_page(response_body)
196208
else:
197209
# assume the response is in protobuf format
@@ -201,7 +213,7 @@ def _apply(self, request_data, expected_response_type=None):
201213
message = common_pb2.WireMessage()
202214
message.ParseFromString(response_body)
203215

204-
logger.debug("Received response\n%s", message.name)
216+
logger.debug("Received response\n%s", message)
205217

206218
if expected_response_type is None:
207219
expected_response_type = request_name.replace('Request', 'Response')
@@ -380,6 +392,7 @@ def prepareAndExecute(self, connectionId, statementId, sql, maxRowCount=-1):
380392
response_data = self._apply(request, 'ExecuteResponse')
381393
response = responses_pb2.ExecuteResponse()
382394
response.ParseFromString(response_data)
395+
logger.info('results %r', response.results)
383396
return response.results
384397

385398
def prepare(self, connectionId, sql, maxRowCount=-1):

phoenixdb/calcite/requests_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phoenixdb/calcite/responses_pb2.py

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

phoenixdb/cursor.py

Lines changed: 5 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -74,12 +74,14 @@ def __exit__(self, exc_type, exc_value, traceback):
7474
def __iter__(self):
7575
return self
7676

77-
def next(self):
77+
def __next__(self):
7878
row = self.fetchone()
7979
if row is None:
8080
raise StopIteration
8181
return row
8282

83+
next = __next__
84+
8385
def close(self):
8486
"""Closes the cursor.
8587
No further operations are allowed once the cursor is closed.
@@ -126,9 +128,6 @@ def _set_id(self, id):
126128
self._id = id
127129

128130
def _set_signature(self, signature):
129-
if signature is not None and signature.SerializeToString() == '':
130-
signature = None
131-
132131
self._signature = signature
133132
self._column_data_types = []
134133
self._parameter_data_types = []
@@ -144,9 +143,6 @@ def _set_signature(self, signature):
144143
self._parameter_data_types.append(dtype)
145144

146145
def _set_frame(self, frame):
147-
if frame is not None and frame.SerializeToString() == '':
148-
frame = None
149-
150146
self._frame = frame
151147
self._pos = None
152148

@@ -167,8 +163,8 @@ def _process_results(self, results):
167163
result = results[0]
168164
if result.own_statement:
169165
self._set_id(result.statement_id)
170-
self._set_signature(result.signature)
171-
self._set_frame(result.first_frame)
166+
self._set_signature(result.signature if result.HasField('signature') else None)
167+
self._set_frame(result.first_frame if result.HasField('first_frame') else None)
172168
self._updatecount = result.update_count
173169

174170
def _transform_parameters(self, parameters):

phoenixdb/errors.py

Lines changed: 8 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -18,18 +18,23 @@
1818
'ProgrammingError', 'NotSupportedError',
1919
]
2020

21+
try:
22+
_StandardError = StandardError
23+
except NameError:
24+
_StandardError = Exception
2125

22-
class Warning(StandardError):
26+
27+
class Warning(_StandardError):
2328
"""Not used by this package, only defined for compatibility
2429
with DB API 2.0."""
2530

2631

27-
class Error(StandardError):
32+
class Error(_StandardError):
2833
"""Exception that is the base class of all other error exceptions.
2934
You can use this to catch all errors with one single except statement."""
3035

3136
def __init__(self, message, code=None, sqlstate=None, cause=None):
32-
super(StandardError, self).__init__(message, code, sqlstate, cause)
37+
super(_StandardError, self).__init__(message, code, sqlstate, cause)
3338

3439
@property
3540
def message(self):

phoenixdb/tests/test_avatica.py

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import unittest
2-
import urlparse
3-
from phoenixdb.avatica import parse_url
2+
from phoenixdb.avatica import parse_url, urlparse
43

54

65
class ParseUrlTest(unittest.TestCase):

phoenixdb/tests/test_dbapi20.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
1-
import dbapi20
21
import unittest
32
import phoenixdb
3+
from . import dbapi20
44
from phoenixdb.tests import TEST_DB_URL
55

66

phoenixdb/tests/test_types.py

Lines changed: 11 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
import sys
12
import unittest
23
import datetime
34
import phoenixdb
@@ -266,23 +267,24 @@ def test_binary(self):
266267
self.createTable("phoenixdb_test_tbl1", "id integer primary key, val binary(2)")
267268
with self.conn.cursor() as cursor:
268269
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, 'ab')")
269-
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [phoenixdb.Binary('ab')])
270+
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [phoenixdb.Binary(b'ab')])
270271
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (3, '\x01\x00')")
271-
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [phoenixdb.Binary('\x01\x00')])
272+
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (4, ?)", [phoenixdb.Binary(b'\x01\x00')])
272273
cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
273274
self.assertEqual(cursor.fetchall(), [
274-
[1, 'ab'],
275-
[2, 'ab'],
276-
[3, '\x01\x00'],
277-
[4, '\x01\x00'],
275+
[1, b'ab'],
276+
[2, b'ab'],
277+
[3, b'\x01\x00'],
278+
[4, b'\x01\x00'],
278279
])
279280

280281
def test_binary_all_bytes(self):
281282
self.createTable("phoenixdb_test_tbl1", "id integer primary key, val binary(256)")
282283
with self.conn.cursor() as cursor:
283-
value = ''
284-
for i in range(256):
285-
value += chr(i)
284+
if sys.version_info[0] < 3:
285+
value = ''.join(map(chr, range(256)))
286+
else:
287+
value = bytes(range(256))
286288
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ?)", [phoenixdb.Binary(value)])
287289
cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
288290
self.assertEqual(cursor.fetchall(), [[1, value]])

0 commit comments

Comments
 (0)