Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
6 changes: 2 additions & 4 deletions README.md
Original file line number Diff line number Diff line change
@@ -1,5 +1,3 @@
# firebolt-sqlalchemy 0.0.1
# firebolt-sqlalchemy

This is a simple example package. You can use
[Github-flavored Markdown](https://guides.github.com/features/mastering-markdown/)
to write your content.
This is the 'alpha' package. Expect updates in future.
24 changes: 24 additions & 0 deletions setup.cfg
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
[metadata]
name = firebolt-sqlalchemy
version = 0.0.1
author = Raghav Sharma
author_email = raghavs@sigmoidanalytics.com
description = Sqlalchemy adapter for Firebolt
long_description = file: README.md
long_description_content_type = text/markdown
url = https://github.com/raghavSharmaSigmoid/firebolt-sqlalchemy
project_urls =
Bug Tracker = https://github.com/raghavSharmaSigmoid/firebolt-sqlalchemy
classifiers =
Programming Language :: Python :: 3
License :: OSI Approved :: MIT License
Operating System :: OS Independent

[options]
package_dir =
= src
packages = find:
python_requires = >=3.6

[options.packages.find]
where = src
11 changes: 8 additions & 3 deletions setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,16 +8,21 @@
version="0.0.1",
author="Raghav Sharma",
author_email="raghavs@sigmoidanalytics.com",
description="Package for Sqlalchemy adapter for Firebolt-Superset integration",
description="Sqlalchemy adapter for Firebolt",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/raghavSharmaSigmoid/sqlalchemy_adapter",
url="https://github.com/raghavSharmaSigmoid/firebolt-sqlalchemy",
project_urls={
"Bug Tracker": "https://github.com/raghavSharmaSigmoid/sqlalchemy_adapter",
"Bug Tracker": "https://github.com/raghavSharmaSigmoid/firebolt-sqlalchemy",
},
install_requires=[
'sqlalchemy>=1.0.0',
"requests"
"json"
"itertools"
"collections"
"datetime"
"functools"
],
entry_points={
"sqlalchemy.dialects": [
Expand Down
10 changes: 2 additions & 8 deletions src/firebolt_db/firebolt_api_service.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class FireboltApiService:

@staticmethod
@memoized
def get_connection(user_email, password, db_name):
def get_connection(user_email, password, db_name, date):
"""
Retrieve Authorisation details for connection
This method internally calls methods to get access token, refresh token and engine URL.
Expand Down Expand Up @@ -202,13 +202,7 @@ def run_query(access_token, refresh_token, engine_url, db_name, query):
query_response.raise_for_status()

except HTTPError as http_err:
if http_err.response.status_code == 401:
access_token = FireboltApiService.get_access_token_via_refresh(refresh_token)
header = {'Authorization': "Bearer " + access_token}
query_response = requests.post(url="https://" + engine_url, params={'database': db_name},
headers=header, files={"query": (None, query)})
else:
payload = {
payload = {
"error": "DB-API Exception",
"errorMessage": http_err.response.text,
}
Expand Down
3 changes: 2 additions & 1 deletion src/firebolt_db/firebolt_connector.py
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
import itertools
import json
from collections import namedtuple, OrderedDict
from datetime import date

from firebolt_db.firebolt_api_service import FireboltApiService
from firebolt_db import exceptions
Expand Down Expand Up @@ -122,7 +123,7 @@ def __init__(self,
self._username = username
self._password = password
self._db_name = db_name
connection_details = FireboltApiService.get_connection(username, password, db_name)
connection_details = FireboltApiService.get_connection(username, password, db_name, date.today())

self.access_token = connection_details[0]
self.engine_url = connection_details[1]
Expand Down
54 changes: 0 additions & 54 deletions temp_test_script.py

This file was deleted.

19 changes: 13 additions & 6 deletions tests/test_firebolt_api_service.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from datetime import date

from firebolt_db.firebolt_api_service import FireboltApiService
from tests import constants
from requests.exceptions import HTTPError
Expand All @@ -12,19 +14,20 @@
class TestFireboltApiService:

def test_get_connection_success(self):
response = FireboltApiService.get_connection(constants.username, constants.password, constants.db_name)
response = FireboltApiService.get_connection(constants.username, constants.password,
constants.db_name, date.today())
if type(response) == HTTPError:
assert response.response.status_code == 503
else:
assert response != ""

def test_get_connection_invalid_credentials(self):
with pytest.raises(Exception) as e_info:
response = FireboltApiService.get_connection('username', 'password', constants.db_name)[0]
response = FireboltApiService.get_connection('username', 'password', constants.db_name, date.today())[0]

def test_get_connection_invalid_schema_name(self):
with pytest.raises(Exception) as e_info:
response = FireboltApiService.get_connection(constants.username, constants.password, 'db_name')[1]
response = FireboltApiService.get_connection(constants.username, constants.password, 'db_name', date.today())[1]

def test_get_access_token_success(self):
assert access_token["access_token"] != ""
Expand Down Expand Up @@ -71,9 +74,13 @@ def test_run_query_invalid_schema(self):
engine_url, 'db_name', constants.query)

def test_run_query_invalid_header(self):
with pytest.raises(Exception) as e_info:
response = FireboltApiService.run_query('header', access_token["refresh_token"], engine_url, constants.db_name,
constants.query) != {}
try:
response = FireboltApiService.run_query('header', access_token["refresh_token"],
engine_url, constants.db_name,
constants.query)
assert response != ""
except exceptions.InternalError as e_info:
assert e_info != ""

def test_run_query_invalid_query(self):
with pytest.raises(Exception) as e_info:
Expand Down
101 changes: 72 additions & 29 deletions tests/test_fireboltconnector.py
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@

@pytest.fixture
def get_connection():
return firebolt_connector.connect('aapurva@sigmoidanalytics.com', 'Apurva111', 'Sigmoid_Alchemy')
return firebolt_connector.connect('localhost', 8123, 'aapurva@sigmoidanalytics.com', 'Apurva111', 'Sigmoid_Alchemy')


class TestConnect:
Expand All @@ -17,27 +17,33 @@ def test_connect_success(self):
user_email = "aapurva@sigmoidanalytics.com"
password = "Apurva111"
db_name = "Sigmoid_Alchemy"
connection = firebolt_connector.connect(user_email, password, db_name)
host = "localhost"
port = "8123"
connection = firebolt_connector.connect(host, port, user_email, password, db_name)
assert connection.access_token
assert connection.engine_url

def test_connect_invalid_credentials(self):
user_email = "aapurva@sigmoidanalytics.com"
password = "wrongpassword"
db_name = "Sigmoid_Alchemy"
host = "localhost"
port = "8123"
with pytest.raises(exceptions.InvalidCredentialsError):
firebolt_connector.connect(user_email, password, db_name)
firebolt_connector.connect(host, port, user_email, password, db_name)

def test_connect_invalid_database(self):
user_email = "aapurva@sigmoidanalytics.com"
password = "Apurva111"
db_name = "wrongdatabase"
host = "localhost"
port = "8123"
with pytest.raises(exceptions.SchemaNotFoundError):
firebolt_connector.connect(user_email, password, db_name)
firebolt_connector.connect(host, port, user_email, password, db_name)


def test_get_description_from_row_valid_rows():
row = {'id': 1, 'name': 'John', 'is_eligible': True}
row = {'id': 1, 'name': 'John', 'is_eligible': True, 'some_array': [2, 4]}
result = firebolt_connector.get_description_from_row(row)
assert result[0][0] == 'id'
assert result[0][1] == firebolt_connector.Type.NUMBER
Expand All @@ -48,10 +54,13 @@ def test_get_description_from_row_valid_rows():
assert result[2][0] == 'is_eligible'
assert result[2][1] == firebolt_connector.Type.BOOLEAN
assert not result[2][6]
assert result[3][0] == 'some_array'
assert result[3][1] == firebolt_connector.Type.ARRAY
assert not result[3][6]


def test_get_description_from_row_invalid_rows():
row = {'id': []}
row = {'id': {}}
with pytest.raises(Exception):
firebolt_connector.get_description_from_row(row)

Expand All @@ -68,8 +77,13 @@ def test_get_type():
assert firebolt_connector.get_type(value_2_2) == 2
assert firebolt_connector.get_type(value_3_1) == 3
assert firebolt_connector.get_type(value_3_2) == 3
assert firebolt_connector.get_type(value_4) == 4


def test_get_type_invalid_type():
value = {}
with pytest.raises(Exception):
firebolt_connector.get_type(value_4)
firebolt_connector.get_type(value)


class TestConnection:
Expand All @@ -81,11 +95,11 @@ def test_cursor(self, get_connection):
assert len(connection.cursors) > 0
assert type(cursor) == firebolt_connector.Cursor

def test_execute(self, get_connection):
connection = get_connection
query = "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.DATABASES"
cursor = connection.execute(query)
assert type(cursor._results) == itertools.chain
# def test_execute(self, get_connection):
# connection = get_connection
# query = "SELECT SCHEMA_NAME FROM INFORMATION_SCHEMA.DATABASES"
# cursor = connection.execute(query)
# assert type(cursor._results) == itertools.chain

def test_commit(self):
pass
Expand All @@ -106,25 +120,54 @@ def test_rowcount(self, get_connection):
cursor = connection.cursor().execute(query)
assert cursor.rowcount == 10

def test_close(self, get_connection):
connection = get_connection
cursor = connection.cursor()
if not cursor.closed:
cursor.close()
assert cursor.closed

def test_close(self):
pass

def test_execute(self):
pass

def test_stream_query(self):
pass

def test_fetchone(self):
pass
def test_execute(self, get_connection):
query = 'select * from lineitem ' \
'where l_orderkey=3184321 and l_partkey=65945'
connection = get_connection
cursor = connection.cursor()
assert not cursor._results
cursor.execute(query)
assert cursor.rowcount == 1

def test_fetchmany(self):
pass
def test_executemany(self, get_connection):
query = "select * from lineitem limit 10"
connection = get_connection
cursor = connection.cursor()
with pytest.raises(exceptions.NotSupportedError):
cursor.executemany(query)

def test_fetchall(self):
pass
def test_fetchone(self, get_connection):
query = "select * from lineitem limit 10"
connection = get_connection
cursor = connection.cursor()
assert not cursor._results
cursor.execute(query)
result = cursor.fetchone()
assert isinstance(result, tuple)

def test_fetchmany(self, get_connection):
query = "select * from lineitem limit 10"
connection = get_connection
cursor = connection.cursor()
assert not cursor._results
cursor.execute(query)
result = cursor.fetchmany(3)
assert isinstance(result, list)
assert len(result) == 3

def test_rows_from_chunks():
pass
def test_fetchall(self, get_connection):
query = "select * from lineitem limit 10"
connection = get_connection
cursor = connection.cursor()
assert not cursor._results
cursor.execute(query)
result = cursor.fetchall()
assert isinstance(result, list)
assert len(result) == 10
Loading