Skip to content
Draft
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
2 changes: 2 additions & 0 deletions san/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,6 +7,7 @@
from .async_batch import AsyncBatch
from .available_metrics import available_metric_for_slug_since, available_metric_versions, available_metrics, available_metrics_for_slug
from .batch import Batch
from .client import SanClient
from .env_vars import SANPY_APIKEY
from .get import get
from .get_many import get_many
Expand Down Expand Up @@ -52,6 +53,7 @@ def get_latest():
"execute_sql",
"metadata",
"metric_complexity",
"SanClient",
"api_calls_made",
"api_calls_remaining",
"is_rate_limit_exception",
Expand Down
24 changes: 20 additions & 4 deletions san/available_metrics.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,13 +4,21 @@


def available_metrics():
return _available_metrics(execute_gql)


def _available_metrics(execute):
sanbase_graphql_functions = inspect.getmembers(san.sanbase_graphql, inspect.isfunction)
all_functions = list(map(lambda x: x[0], sanbase_graphql_functions)) + execute_gql("{query: getAvailableMetrics}")["query"]
all_functions = list(map(lambda x: x[0], sanbase_graphql_functions)) + execute("{query: getAvailableMetrics}")["query"]
all_functions = list(filter(lambda x: not (str.startswith(x, "get_metric") or str.startswith(x, "_")), all_functions))
return all_functions


def available_metrics_for_slug(slug):
return _available_metrics_for_slug(execute_gql, slug)


def _available_metrics_for_slug(execute, slug):
query_str = (
"""{{
projectBySlug(slug: \"{slug}\"){{
Expand All @@ -20,10 +28,14 @@ def available_metrics_for_slug(slug):
"""
).format(slug=slug)

return execute_gql(query_str)["projectBySlug"]["availableMetrics"]
return execute(query_str)["projectBySlug"]["availableMetrics"]


def available_metric_versions(metric):
return _available_metric_versions(execute_gql, metric)


def _available_metric_versions(execute, metric):
query_str = (
"""{{
getMetric(metric: \"{metric}\"){{
Expand All @@ -35,14 +47,18 @@ def available_metric_versions(metric):
"""
).format(metric=metric)

result = execute_gql(query_str)
result = execute(query_str)
get_metric = result.get("getMetric") or {}
metadata = get_metric.get("metadata") or {}
versions = metadata.get("availableVersions") or []
return [v["version"] for v in versions]


def available_metric_for_slug_since(metric, slug):
return _available_metric_for_slug_since(execute_gql, metric, slug)


def _available_metric_for_slug_since(execute, metric, slug):
query_str = (
"""{{
getMetric(metric: \"{metric}\"){{
Expand All @@ -52,4 +68,4 @@ def available_metric_for_slug_since(metric, slug):
"""
).format(metric=metric, slug=slug)

return execute_gql(query_str)["getMetric"]["availableSince"]
return execute(query_str)["getMetric"]["availableSince"]
57 changes: 57 additions & 0 deletions san/client.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
from san.available_metrics import (
_available_metric_for_slug_since,
_available_metric_versions,
_available_metrics,
_available_metrics_for_slug,
)
from san.execute_sql import _execute_sql_with_executor
from san.get import _get_with_executor
from san.get_many import _get_many_with_executor
from san.graphql import DEFAULT_TRANSPORT, _execute_gql, _get_response_headers
from san.metadata import _metadata
from san.metric_complexity import _metric_complexity
from san.utility import _api_calls_made, _api_calls_remaining


class SanClient:
def __init__(self, api_key=None):
self.api_key = api_key

def execute_gql(self, gql_query_str):
return _execute_gql(gql_query_str, transport=DEFAULT_TRANSPORT, api_key=self.api_key)

def get_response_headers(self, gql_query_str):
return _get_response_headers(gql_query_str, transport=DEFAULT_TRANSPORT, api_key=self.api_key)

def get(self, dataset, **kwargs):
return _get_with_executor(dataset, self.execute_gql, "SanClient.get", **kwargs)

def get_many(self, dataset, **kwargs):
return _get_many_with_executor(dataset, self.execute_gql, "SanClient.get_many", **kwargs)

def execute_sql(self, **kwargs):
return _execute_sql_with_executor(self.execute_gql, **kwargs)

def available_metrics(self):
return _available_metrics(self.execute_gql)

def available_metrics_for_slug(self, slug):
return _available_metrics_for_slug(self.execute_gql, slug)

def available_metric_versions(self, metric):
return _available_metric_versions(self.execute_gql, metric)

def available_metric_for_slug_since(self, metric, slug):
return _available_metric_for_slug_since(self.execute_gql, metric, slug)

def metadata(self, metric, arr):
return _metadata(self.execute_gql, metric, arr)

def metric_complexity(self, metric, from_date, to_date, interval):
return _metric_complexity(self.execute_gql, metric, from_date, to_date, interval)

def api_calls_remaining(self):
return _api_calls_remaining(self.get_response_headers)

def api_calls_made(self):
return _api_calls_made(self.execute_gql)
10 changes: 7 additions & 3 deletions san/execute_sql.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,20 +25,24 @@ def execute_sql(**kwargs):
parameters={'slug': 'bitcoin', 'metric': 'daily_active_addresses', 'last_n_days': 7},
set_index="dt")
"""
return _execute_sql_with_executor(execute_gql, **kwargs)


def _execute_sql_with_executor(execute, **kwargs):
if "query" in kwargs:
query = kwargs.pop("query")
else:
raise SanError("The 'query' argument is required when calling 'execute_sql'")

parameters = kwargs.pop("parameters", {})

result = __execute_sql(query, parameters, **kwargs)
result = __execute_sql(execute, query, parameters, **kwargs)
transformed_result = result

return transformed_result


def __execute_sql(query, parameters, **kwargs):
def __execute_sql(execute, query, parameters, **kwargs):
idx = kwargs.pop("idx", 0)
# Export the python dictionary parameters to a JSON string
# where each of the quotes " is replaced with \", so when interpolated
Expand All @@ -60,7 +64,7 @@ def __execute_sql(query, parameters, **kwargs):
}}
}}"""

res = execute_gql(gql_query)
res = execute(gql_query)
res = __transform_sql_result(res, idx, **kwargs)

return res
Expand Down
18 changes: 11 additions & 7 deletions san/get.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,15 +37,19 @@ def get(dataset, **kwargs):
from_date="utc_now-60d",
to_date="utc_now-40d")
"""
validate_kwargs("san.get", kwargs)
return _get_with_executor(dataset, execute_gql, "san.get", **kwargs)


def _get_with_executor(dataset, execute, func_name, **kwargs):
validate_kwargs(func_name, kwargs)
query, slug = parse_dataset(dataset)
if slug or query in NO_SLUG_QUERIES:
return __get_metric_slug_string_selector(query, slug, dataset, **kwargs)
return __get_metric_slug_string_selector(query, slug, dataset, execute, **kwargs)
elif query and not slug:
return __get(query, **kwargs)
return __get(query, execute, **kwargs)


def __get_metric_slug_string_selector(query, slug, dataset, **kwargs):
def __get_metric_slug_string_selector(query, slug, dataset, execute, **kwargs):
idx = kwargs.pop("idx", 0)

if query in DEPRECATED_QUERIES:
Expand All @@ -64,12 +68,12 @@ def __get_metric_slug_string_selector(query, slug, dataset, **kwargs):
gql_query = "{" + san.sanbase_graphql.get_metric_timeseries_data(idx, query, slug, **kwargs) + "}"
else:
raise SanError("Invalid metric!")
res = execute_gql(gql_query)
res = execute(gql_query)

return transform_timeseries_data_query_result(idx, query, res)


def __get(query, **kwargs):
def __get(query, execute, **kwargs):
if not ("selector" in kwargs or "slug" in kwargs):
raise SanError("""
Invalid call of the get function,you need to either
Expand All @@ -82,6 +86,6 @@ def __get(query, **kwargs):
else:
gql_query = "{" + san.sanbase_graphql.get_metric_timeseries_data(idx, query, **kwargs) + "}"

res = execute_gql(gql_query)
res = execute(gql_query)

return transform_timeseries_data_query_result(idx, query, res)
10 changes: 5 additions & 5 deletions san/get_many.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,12 +14,12 @@ def get_many(dataset, **kwargs):
from_date="2020-01-01"
to_date="2020-01-10")
"""
validate_kwargs("san.get_many", kwargs)
query, slug = parse_dataset(dataset)
return __get_many(query, **kwargs)
return _get_many_with_executor(dataset, execute_gql, "san.get_many", **kwargs)


def __get_many(query, **kwargs):
def _get_many_with_executor(dataset, execute, func_name, **kwargs):
validate_kwargs(func_name, kwargs)
query, _ = parse_dataset(dataset)
if not ("selector" in kwargs or "slugs" in kwargs):
raise SanError("""
Invalid call of the get function,you need to either
Expand All @@ -28,6 +28,6 @@ def __get_many(query, **kwargs):
idx = kwargs.pop("idx", 0)

gql_query = "{" + san.sanbase_graphql.get_metric_timeseries_data_per_slug(idx, query, **kwargs) + "}"
res = execute_gql(gql_query)
res = execute(gql_query)

return transform_timeseries_data_per_slug_query_result(idx, query, res)
20 changes: 14 additions & 6 deletions san/graphql.py
Original file line number Diff line number Diff line change
Expand Up @@ -13,15 +13,23 @@


def execute_gql(gql_query_str):
response = DEFAULT_TRANSPORT.execute(gql_query_str, headers=__build_headers())
return _execute_gql(gql_query_str, transport=DEFAULT_TRANSPORT, api_key=ApiConfig.api_key)


def get_response_headers(gql_query_str):
return _get_response_headers(gql_query_str, transport=DEFAULT_TRANSPORT, api_key=ApiConfig.api_key)


def _execute_gql(gql_query_str, transport, api_key=None):
response = transport.execute(gql_query_str, headers=__build_headers(api_key))

if response.status_code == 200:
return __handle_success_response__(response, gql_query_str)
__raise_response_error__(response, gql_query_str)


def get_response_headers(gql_query_str):
response = DEFAULT_TRANSPORT.execute(gql_query_str, headers=__build_headers())
def _get_response_headers(gql_query_str, transport, api_key=None):
response = transport.execute(gql_query_str, headers=__build_headers(api_key))

if response.status_code == 200:
return response.headers
Expand All @@ -41,10 +49,10 @@ def __handle_success_response__(response, gql_query_str):
)


def __build_headers():
def __build_headers(api_key):
headers = {}
if ApiConfig.api_key:
headers = {"authorization": "Apikey {}".format(ApiConfig.api_key)}
if api_key:
headers = {"authorization": "Apikey {}".format(api_key)}
return headers


Expand Down
6 changes: 5 additions & 1 deletion san/metadata.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@


def metadata(metric, arr):
return _metadata(execute_gql, metric, arr)


def _metadata(execute, metric, arr):
query_str = (
"""{{
getMetric (metric: \"{metric}\") {{
Expand All @@ -15,4 +19,4 @@ def metadata(metric, arr):
"""
).format(metric=metric)

return execute_gql(query_str)["getMetric"]["metadata"]
return execute(query_str)["getMetric"]["metadata"]
6 changes: 5 additions & 1 deletion san/metric_complexity.py
Original file line number Diff line number Diff line change
Expand Up @@ -3,6 +3,10 @@


def metric_complexity(metric, from_date, to_date, interval):
return _metric_complexity(execute_gql, metric, from_date, to_date, interval)


def _metric_complexity(execute, metric, from_date, to_date, interval):
query_str = (
"""{{
getMetric (metric: \"{metric}\") {{
Expand All @@ -16,4 +20,4 @@ def metric_complexity(metric, from_date, to_date, interval):
"""
).format(metric=metric, from_date=_format_from_date(from_date), to_date=_format_to_date(to_date), interval=interval)

return execute_gql(query_str)["getMetric"]["timeseriesDataComplexity"]
return execute(query_str)["getMetric"]["timeseriesDataComplexity"]
Loading