Commit ddc4dc06 by Lukáš Lalinský

Add flake8 tests

parent e01be396
Pipeline #18656 failed with stages
in 5 minutes 59 seconds
......@@ -15,8 +15,8 @@
from phoenixdb import errors, types
from phoenixdb.avatica import AvaticaClient
from phoenixdb.connection import Connection
from phoenixdb.errors import *
from phoenixdb.types import *
from phoenixdb.errors import * # noqa: F401,F403
from phoenixdb.types import * # noqa: F401,F403
__all__ = ['connect', 'apilevel', 'threadsafety', 'paramstyle'] + types.__all__ + errors.__all__
......
......@@ -77,21 +77,21 @@ def parse_url(url):
# Defined in phoenix-core/src/main/java/org/apache/phoenix/exception/SQLExceptionCode.java
SQLSTATE_ERROR_CLASSES = [
('08', errors.OperationalError), # Connection Exception
('22018', errors.IntegrityError), # Constraint violatioin.
('22', errors.DataError), # Data Exception
('23', errors.IntegrityError), # Constraint Violation
('24', errors.InternalError), # Invalid Cursor State
('25', errors.InternalError), # Invalid Transaction State
('42', errors.ProgrammingError), # Syntax Error or Access Rule Violation
('XLC', errors.OperationalError), # Execution exceptions
('INT', errors.InternalError), # Phoenix internal error
('08', errors.OperationalError), # Connection Exception
('22018', errors.IntegrityError), # Constraint violatioin.
('22', errors.DataError), # Data Exception
('23', errors.IntegrityError), # Constraint Violation
('24', errors.InternalError), # Invalid Cursor State
('25', errors.InternalError), # Invalid Transaction State
('42', errors.ProgrammingError), # Syntax Error or Access Rule Violation
('XLC', errors.OperationalError), # Execution exceptions
('INT', errors.InternalError), # Phoenix internal error
]
# Relevant properties as defined by https://calcite.apache.org/avatica/docs/client_reference.html
OPEN_CONNECTION_PROPERTIES = (
'user', # User for the database connection
'password', # Password for the user
'user', # User for the database connection
'password', # Password for the user
)
......@@ -163,7 +163,7 @@ class AvaticaClient(object):
logger.debug("Closing connection to %s:%s", self.url.hostname, self.url.port)
try:
self.connection.close()
except httplib.HTTPException as e:
except httplib.HTTPException:
logger.warning("Error while closing connection", exc_info=True)
self.connection = None
......
......@@ -18,7 +18,7 @@ import weakref
from phoenixdb import errors
from phoenixdb.avatica import OPEN_CONNECTION_PROPERTIES
from phoenixdb.cursor import Cursor
from phoenixdb.errors import OperationalError, NotSupportedError, ProgrammingError
from phoenixdb.errors import ProgrammingError
__all__ = ['Connection']
......@@ -174,7 +174,7 @@ class Connection(object):
def transactionisolation(self):
return self._transactionisolation
@readonly.setter
@transactionisolation.setter
def transactionisolation(self, value):
if self._closed:
raise ProgrammingError('the connection is already closed')
......
......@@ -15,7 +15,7 @@
import logging
import collections
from phoenixdb.types import TypeHelper
from phoenixdb.errors import OperationalError, NotSupportedError, ProgrammingError, InternalError
from phoenixdb.errors import ProgrammingError, InternalError
from phoenixdb.calcite import common_pb2
__all__ = ['Cursor', 'ColumnDescription', 'DictCursor']
......@@ -28,6 +28,7 @@ MAX_INT = 2 ** 64 - 1
ColumnDescription = collections.namedtuple('ColumnDescription', 'name type_code display_size internal_size precision scale null_ok')
"""Named tuple for representing results from :attr:`Cursor.description`."""
class Cursor(object):
"""Database cursor for executing queries and iterating over results.
......@@ -154,7 +155,8 @@ class Cursor(object):
def _fetch_next_frame(self):
offset = self._frame.offset + len(self._frame.rows)
frame = self._connection._client.fetch(self._connection._id, self._id,
frame = self._connection._client.fetch(
self._connection._id, self._id,
offset=offset, frame_max_size=self.itersize)
self._set_frame(frame)
......@@ -197,16 +199,18 @@ class Cursor(object):
if parameters is None:
if self._id is None:
self._set_id(self._connection._client.create_statement(self._connection._id))
results = self._connection._client.prepare_and_execute(self._connection._id, self._id,
results = self._connection._client.prepare_and_execute(
self._connection._id, self._id,
operation, first_frame_max_size=self.itersize)
self._process_results(results)
else:
statement = self._connection._client.prepare(self._connection._id,
operation)
statement = self._connection._client.prepare(
self._connection._id, operation)
self._set_id(statement.id)
self._set_signature(statement.signature)
results = self._connection._client.execute(self._connection._id, self._id,
results = self._connection._client.execute(
self._connection._id, self._id,
statement.signature, self._transform_parameters(parameters),
first_frame_max_size=self.itersize)
self._process_results(results)
......@@ -216,13 +220,14 @@ class Cursor(object):
raise ProgrammingError('the cursor is already closed')
self._updatecount = -1
self._set_frame(None)
statement = self._connection._client.prepare(self._connection._id,
operation, max_rows_total=0)
statement = self._connection._client.prepare(
self._connection._id, operation, max_rows_total=0)
self._set_id(statement.id)
self._set_signature(statement.signature)
for parameters in seq_of_parameters:
self._connection._client.execute(self._connection._id, self._id,
statement.signature, self._transform_parameters(parameters),
self._connection._client.execute(
self._connection._id, self._id,
statement.signature, self._transform_parameters(parameters),
first_frame_max_size=0)
def _transform_row(self, row):
......@@ -300,7 +305,8 @@ class Cursor(object):
@property
def connection(self):
"""Read-only attribute providing access to the :class:`Connection <phoenixdb.connection.Connection>` object this cursor was created from."""
"""Read-only attribute providing access to the :class:`Connection <phoenixdb.connection.Connection>`
object this cursor was created from."""
return self._connection
@property
......
......@@ -7,7 +7,7 @@ TEST_DB_URL = os.environ.get('PHOENIXDB_TEST_DB_URL')
@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
class DatabaseTestCase(unittest.TestCase):
def setUp(self):
self.conn = phoenixdb.connect(TEST_DB_URL, autocommit=True)
self.cleanup_tables = []
......
import unittest
import phoenixdb
from . import dbapi20
from phoenixdb.tests import TEST_DB_URL
@unittest.skipIf(TEST_DB_URL is None, "these tests require the PHOENIXDB_TEST_DB_URL environment variable set to a clean database")
class PhoenixConnectionTest(unittest.TestCase):
def _connect(self, connect_kw_args):
try:
r = phoenixdb.connect(
*(TEST_DB_URL, ), **connect_kw_args
)
r = phoenixdb.connect(TEST_DB_URL, **connect_kw_args)
except AttributeError:
self.fail("Failed to connect")
return r
def test_connection_credentials(self):
connect_kw_args = {'user':'SCOTT', 'password':'TIGER', 'readonly':'True'}
connect_kw_args = {'user': 'SCOTT', 'password': 'TIGER', 'readonly': 'True'}
con = self._connect(connect_kw_args)
try:
self.assertEqual(con._connection_args, {'user':'SCOTT', 'password':'TIGER'},
'Should have extract user and password'
)
self.assertEqual(con._filtered_args, {'readonly':'True'},
'Should have not extracted foo'
)
self.assertEqual(
con._connection_args, {'user': 'SCOTT', 'password': 'TIGER'},
'Should have extract user and password')
self.assertEqual(
con._filtered_args, {'readonly': 'True'},
'Should have not extracted foo')
finally:
con.close()
......@@ -13,8 +13,11 @@ class PhoenixDatabaseAPI20Test(dbapi20.DatabaseAPI20Test):
ddl2 = 'create table %sbarflys (name varchar(20) primary key, drink varchar(30))' % dbapi20.DatabaseAPI20Test.table_prefix
insert = 'upsert'
def test_nextset(self): pass
def test_setoutputsize(self): pass
def test_nextset(self):
pass
def test_setoutputsize(self):
pass
def _connect(self):
con = dbapi20.DatabaseAPI20Test._connect(self)
......@@ -29,9 +32,9 @@ class PhoenixDatabaseAPI20Test(dbapi20.DatabaseAPI20Test):
cur.execute("%s into %sbarflys values ('a', NULL)" % (self.insert, self.table_prefix))
cur.execute('select drink from %sbarflys' % self.table_prefix)
r = cur.fetchall()
self.assertEqual(len(r),1)
self.assertEqual(len(r[0]),1)
self.assertEqual(r[0][0],None,'NULL value not returned as None')
self.assertEqual(len(r), 1)
self.assertEqual(len(r[0]), 1)
self.assertEqual(r[0][0], None, 'NULL value not returned as None')
finally:
con.close()
......@@ -58,8 +61,8 @@ class PhoenixDatabaseAPI20Test(dbapi20.DatabaseAPI20Test):
con = self._connect()
try:
cur = con.cursor()
if hasattr(cur,'__iter__'):
self.assertIs(cur,iter(cur))
if hasattr(cur, '__iter__'):
self.assertIs(cur, iter(cur))
finally:
con.close()
......@@ -68,41 +71,37 @@ class PhoenixDatabaseAPI20Test(dbapi20.DatabaseAPI20Test):
con = self._connect()
try:
cur = con.cursor()
if not hasattr(cur,'next'):
if not hasattr(cur, 'next'):
return
# cursor.next should raise an Error if called before
# executing a select-type query
self.assertRaises(self.driver.Error,cur.next)
self.assertRaises(self.driver.Error, cur.next)
# cursor.next should raise an Error if called after
# executing a query that cannnot return rows
self.executeDDL1(cur)
self.assertRaises(self.driver.Error,cur.next)
self.assertRaises(self.driver.Error, cur.next)
# cursor.next should return None if a query retrieves '
# no rows
cur.execute('select name from %sbooze' % self.table_prefix)
self.assertRaises(StopIteration,cur.next)
self.failUnless(cur.rowcount in (-1,0))
self.assertRaises(StopIteration, cur.next)
self.failUnless(cur.rowcount in (-1, 0))
# cursor.next should raise an Error if called after
# executing a query that cannnot return rows
cur.execute("%s into %sbooze values ('Victoria Bitter')" % (
self.insert, self.table_prefix
))
self.assertRaises(self.driver.Error,cur.next)
self.assertRaises(self.driver.Error, cur.next)
cur.execute('select name from %sbooze' % self.table_prefix)
r = cur.next()
self.assertEqual(len(r),1,
'cursor.next should have retrieved a row with one column'
)
self.assertEqual(r[0],'Victoria Bitter',
'cursor.next retrieved incorrect data'
)
self.assertEqual(len(r), 1, 'cursor.next should have retrieved a row with one column')
self.assertEqual(r[0], 'Victoria Bitter', 'cursor.next retrieved incorrect data')
# cursor.next should raise StopIteration if no more rows available
self.assertRaises(StopIteration,cur.next)
self.failUnless(cur.rowcount in (-1,1))
self.assertRaises(StopIteration, cur.next)
self.failUnless(cur.rowcount in (-1, 1))
finally:
con.close()
......@@ -21,11 +21,17 @@ class TypesTest(DatabaseTestCase):
self.assertEqual(cursor.description[1].type_code, phoenixdb.NUMBER)
self.assertEqual(cursor.fetchall(), [[1, 1], [2, None], [3, 1], [4, None], [5, min_value], [6, max_value]])
self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(min_value - 1))
self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(max_value + 1))
self.assertRaises(
self.conn.DatabaseError, cursor.execute,
"UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(min_value - 1))
self.assertRaises(
self.conn.DatabaseError, cursor.execute,
"UPSERT INTO phoenixdb_test_tbl1 VALUES (100, {})".format(max_value + 1))
# XXX The server silently truncates the values
#self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [min_value - 1])
#self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [max_value + 1])
# self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [min_value - 1])
# self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [max_value + 1])
def test_integer(self):
self.checkIntType("integer", -2147483648, 2147483647)
......@@ -100,8 +106,12 @@ class TypesTest(DatabaseTestCase):
self.assertEqual(rows[2][1], Decimal('33333.333'))
self.assertEqual(rows[3][1], Decimal('33333.333'))
self.assertEqual(rows[4][1], None)
self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [Decimal('1234567890')])
self.assertRaises(self.conn.DatabaseError, cursor.execute, "UPSERT INTO phoenixdb_test_tbl1 VALUES (101, ?)", [Decimal('123456.789')])
self.assertRaises(
self.conn.DatabaseError, cursor.execute,
"UPSERT INTO phoenixdb_test_tbl1 VALUES (100, ?)", [Decimal('1234567890')])
self.assertRaises(
self.conn.DatabaseError, cursor.execute,
"UPSERT INTO phoenixdb_test_tbl1 VALUES (101, ?)", [Decimal('123456.789')])
def test_boolean(self):
self.createTable("phoenixdb_test_tbl1", "id integer primary key, val boolean")
......@@ -175,7 +185,7 @@ class TypesTest(DatabaseTestCase):
with self.conn.cursor() as cursor:
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, NULL)")
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [None])
cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id") # raises NullPointerException on the server
cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id") # raises NullPointerException on the server
self.assertEqual(cursor.fetchall(), [
[1, None],
[2, None],
......@@ -293,10 +303,10 @@ class TypesTest(DatabaseTestCase):
def test_array(self):
self.createTable("phoenixdb_test_tbl1", "id integer primary key, val integer[]")
with self.conn.cursor() as cursor:
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ARRAY[1,2])")
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [[2,3]])
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (1, ARRAY[1, 2])")
cursor.execute("UPSERT INTO phoenixdb_test_tbl1 VALUES (2, ?)", [[2, 3]])
cursor.execute("SELECT id, val FROM phoenixdb_test_tbl1 ORDER BY id")
self.assertEqual(cursor.fetchall(), [
[1, [1,2]],
[2, [2,3]],
[1, [1, 2]],
[2, [2, 3]],
])
......@@ -113,7 +113,10 @@ STRING = ColumnType(['VARCHAR', 'CHAR'])
BINARY = ColumnType(['BINARY', 'VARBINARY'])
"""Type object that can be used to describe (long) binary columns."""
NUMBER = ColumnType(['INTEGER', 'UNSIGNED_INT', 'BIGINT', 'UNSIGNED_LONG', 'TINYINT', 'UNSIGNED_TINYINT', 'SMALLINT', 'UNSIGNED_SMALLINT', 'FLOAT', 'UNSIGNED_FLOAT', 'DOUBLE', 'UNSIGNED_DOUBLE', 'DECIMAL'])
NUMBER = ColumnType([
'INTEGER', 'UNSIGNED_INT', 'BIGINT', 'UNSIGNED_LONG', 'TINYINT', 'UNSIGNED_TINYINT',
'SMALLINT', 'UNSIGNED_SMALLINT', 'FLOAT', 'UNSIGNED_FLOAT', 'DOUBLE', 'UNSIGNED_DOUBLE', 'DECIMAL'
])
"""Type object that can be used to describe numeric columns."""
DATETIME = ColumnType(['TIME', 'DATE', 'TIMESTAMP', 'UNSIGNED_TIME', 'UNSIGNED_DATE', 'UNSIGNED_TIMESTAMP'])
......@@ -157,7 +160,7 @@ JAVA_CLASSES = {
}
"""Groups of Java classes."""
JAVA_CLASSES_MAP = dict( (v[0], (k, v[1], v[2], v[3])) for k in JAVA_CLASSES for v in JAVA_CLASSES[k] )
JAVA_CLASSES_MAP = dict((v[0], (k, v[1], v[2], v[3])) for k in JAVA_CLASSES for v in JAVA_CLASSES[k])
"""Flips the available types to allow for faster lookup by Java class.
This mapping should be structured as:
......
......@@ -10,3 +10,10 @@ all_files = 1
[upload_sphinx]
upload-dir = doc/build/html
[flake8]
max-line-length = 140
exclude =
e,env,venv,doc,build,dist,.tox,.idea,
./phoenixdb/tests/dbapi20.py,
./phoenixdb/calcite/*_pb2.py
......@@ -8,10 +8,12 @@ try:
except ImportError:
pass
def readme():
with open('README.rst') as f:
return f.read()
version = "0.7"
setup(
......
......@@ -3,5 +3,7 @@ envlist = py27,py35,py36
[testenv]
passenv = PHOENIXDB_TEST_DB_URL
commands = {envbindir}/nosetests -v
commands =
flake8
nosetests -v
deps = -rrequirements.txt
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment