Skip to content

Commit

Permalink
TRA-4042: Update Version (#44)
Browse files Browse the repository at this point in the history
  • Loading branch information
tannishmango committed Feb 29, 2024
1 parent 7b30028 commit a797e04
Show file tree
Hide file tree
Showing 9 changed files with 70 additions and 40 deletions.
11 changes: 11 additions & 0 deletions README.md
Expand Up @@ -37,6 +37,17 @@ You can find specific documentation on a per-product basis below.
## SDK Documentation
You can learn more about the Transpose SDK and how it works below.

### SDK Helpers

#### stringify_list
Converts a list of strings into a single string, separated by a delimiter.

```python
from transpose.src.util.format import stringify_list

stringify_list(['a', 'b', 'c'], ',')
>>> 'a,b,c'
```

### SDK Classes
The Transpose SDK uses custom classes to represent API responses:
Expand Down
6 changes: 3 additions & 3 deletions setup.py
Expand Up @@ -8,7 +8,7 @@

# version compliant with PEP440
# https://peps.python.org/pep-0440/
version='4.0.2',
version='4.2.0',

# project meta
long_description = long_description,
Expand All @@ -33,8 +33,8 @@
url='https://github.com/TransposeData/transpose-python-sdk',

# Author details
author='Michael Calvey (michaeljohncalvey), Alex Langshur (alangshur), Jonathan Becker (jon-becker)',
author_email='michael@transpose.io, alex@transpose.io, jon@transpose.io',
author='Michael Calvey (michaeljohncalvey), Alex Langshur (alangshur), Jonathan Becker (jon-becker), Patrick Croke (tannishmango)',
author_email='michael@transpose.io, alex@transpose.io, jon@transpose.io, patrick@transpose.io',

# Find all packages in the directory
packages=find_packages(exclude=['tests', 'demo', 'docs']),
Expand Down
6 changes: 4 additions & 2 deletions tests/test_analytical.py
Expand Up @@ -70,8 +70,10 @@ def test_query_df():

try:
api = Transpose(api_key)

response = api.analytical.query("SELECT * FROM cross_chain.transaction_flows LIMIT 10;", return_df=True)
query = "SELECT * FROM cross_chain.transaction_flows LIMIT 10;"
response = api.analytical.query(
query
).toPandas()

assert len(response) == 10
assert isinstance(response, DataFrame)
Expand Down
3 changes: 2 additions & 1 deletion tests/test_sql.py
Expand Up @@ -50,7 +50,8 @@ def test_query_df():
try:
api = Transpose(api_key)

response = api.sql.query("SELECT * FROM ethereum.logs LIMIT 100;", return_df=True)
query = "SELECT * FROM ethereum.logs LIMIT 100;"
response = api.sql.query(query).toPandas()

assert type(response) is DataFrame
assert len(response) == 100
Expand Down
9 changes: 5 additions & 4 deletions transpose/src/api/analytical/base.py
@@ -1,3 +1,4 @@
from ...util.models import QueryResult
from ....src.util.client import post_api_request


Expand All @@ -11,8 +12,7 @@ def query(
self,
sql_query: str,
parameters: dict = None,
return_df: bool = False
) -> dict:
) -> QueryResult:

parameters = {} if parameters is None else parameters

Expand All @@ -22,10 +22,11 @@ def query(
'parameters': parameters
}

return post_api_request(
result = post_api_request(
url=url,
api_key=self.super.api_key,
body=body,
return_df=return_df,
verbose=self.super.verbose
)

return QueryResult(result)
9 changes: 5 additions & 4 deletions transpose/src/api/sql/base.py
@@ -1,3 +1,4 @@
from ...util.models import QueryResult
from ....src.util.client import get_api_request, post_api_request


Expand All @@ -11,23 +12,23 @@ def query(
self,
sql_query: str,
parameters: dict = {},
return_df: bool = False
) -> dict:
) -> QueryResult:

url = "https://api.transpose.io/sql"
body = {
'sql': sql_query,
'parameters': parameters
}

return post_api_request(
result = post_api_request(
url=url,
api_key=self.super.api_key,
body=body,
return_df=return_df,
verbose=self.super.verbose
)

return QueryResult(result)

# Gets the schema from the Transpose API
def schema(self) -> dict:

Expand Down
28 changes: 7 additions & 21 deletions transpose/src/util/client.py
@@ -1,9 +1,5 @@
import json
from typing import Union

import requests
import pandas as pd
from pandas import DataFrame

from transpose.src.util.errors import raise_custom_error

Expand All @@ -16,22 +12,14 @@ def build_headers(api_key: str) -> dict:
}


def handle_response(request: requests.Response, return_df: bool = False) -> Union[dict, DataFrame]:
if request.status_code == 200:

# return the response as a DataFrame
if return_df:

# check if pandas is installed
if not pd:
raise ImportError("Pandas is not installed. Please install pandas to use this feature.")

return pd.DataFrame(request.json()['results'])
def handle_response(request: requests.Response) -> dict:

if request.status_code == 200:
# return the response as a dictionary
return request.json()

else:

raise_custom_error(request.status_code, request.json()['message'])


Expand All @@ -40,9 +28,8 @@ def get_api_request(
api_key: str,
body: dict = None,
params=None,
return_df: bool = False,
verbose: bool = False
) -> Union[dict, DataFrame]:
) -> dict:

# set body/parameters to an empty dictionary if not provided
body = {} if body is None else body
Expand All @@ -60,17 +47,16 @@ def get_api_request(
params=params
)

return handle_response(request, return_df)
return handle_response(request)


def post_api_request(
url: str,
api_key: str,
body: dict,
params=None,
return_df: bool = False,
verbose: bool = False
) -> Union[dict, DataFrame]:
) -> dict:

# set body/parameters to an empty dictionary if not provided
body = {} if body is None else body
Expand All @@ -88,4 +74,4 @@ def post_api_request(
params=params
)

return handle_response(request, return_df)
return handle_response(request)
4 changes: 4 additions & 0 deletions transpose/src/util/format.py
@@ -0,0 +1,4 @@


def stringify_list(data: list[str], delimiter: str = ",") -> str:
return delimiter.join([f"'{x}'" for x in data])
34 changes: 29 additions & 5 deletions transpose/src/util/models.py
@@ -1,18 +1,42 @@
import io
import json
import base64

from typing import List

import pandas as pd


# add a .to_dict and .__dict__ method to the list base class
class list(list):
def to_dict(self):
return [obj.to_dict() for obj in self]

def __dict__(self):
return [obj.to_dict() for obj in self]



class QueryResult:
def __init__(self, result):
self.result = result

def toPandas(self):
# Assumes the result is a dictionary and the data is in the 'results' key
return pd.DataFrame(self.result['results'])

def keys(self):
return self.result.keys()

def values(self):
return self.result.values()

def __getitem__(self, key):
return self.result[key]

def __setitem__(self, key, value):
self.result[key] = value

def __delitem__(self, key):
del self.result[key]

def __iter__(self):
return iter(self.result)
# these are used in static typing so we can return useful tooltips for users
# and allow for proper type checking and syntax highlighting

Expand Down

0 comments on commit a797e04

Please sign in to comment.