Skip to content

Commit 91289d5

Browse files
authored
Release v4.1.0 (#137)
1 parent 66d7b27 commit 91289d5

File tree

177 files changed

+8069
-3231
lines changed

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

177 files changed

+8069
-3231
lines changed

.pylintrc

Lines changed: 0 additions & 36 deletions
This file was deleted.

Jenkinsfile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -171,7 +171,7 @@ String getSlackUser() {
171171

172172
String getChannel() {
173173
if (ON_MAIN) {
174-
return '#jenkins-ci'
174+
return '#build-notifications'
175175
}
176176
return "@${getSlackUser()}"
177177
}

Pipfile

Lines changed: 4 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,16 +5,17 @@ name = "pypi"
55

66
[packages]
77
black = "*"
8-
google-api-core = ">1.31.3"
8+
google-api-core = "*"
99
google-cloud-bigquery = "*"
10-
googleapis-common-protos = ">=1.56.0*"
10+
googleapis-common-protos = "*"
1111
grpcio = "*"
1212
isort = "*"
1313
mypy = "*"
1414
openpyxl = "*"
1515
pandas = "*"
1616
protobuf = "*"
17-
pycodestyle = "*"
17+
pyathena = "*"
18+
pyarrow = "*"
1819
pylint = "*"
1920
requests = "*"
2021
setuptools = "*"

Pipfile.lock

Lines changed: 637 additions & 571 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

README.md

Lines changed: 2 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,12 +21,13 @@ For installation with support for exporting data from a various SQL based data s
2121
pip install exabel-data-sdk[snowflake]
2222

2323
# Or install multiple data sources at the same time:
24-
pip install exabel-data-sdk[snowflake,bigquery]
24+
pip install exabel-data-sdk[snowflake,bigquery,athena]
2525
```
2626

2727
Supported data sources are:
2828
* Snowflake: `snowflake`
2929
* Google BigQuery: `bigquery`
30+
* AWS Athena: `athena`
3031

3132
## Getting started
3233

VERSION

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1 +1 @@
1-
4.0.0
1+
4.1.0

exabel_data_sdk/client/api/api_client/grpc/base_grpc_client.py

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@
33
from exabel_data_sdk.client.api.api_client.exabel_api_group import ExabelApiGroup
44
from exabel_data_sdk.client.client_config import ClientConfig
55

6+
SIXTEEN_MEGABYTES_IN_BYTES = 16 * 1024 * 1024
7+
68

79
class BaseGrpcClient:
810
"""
@@ -12,17 +14,23 @@ class BaseGrpcClient:
1214
def __init__(self, config: ClientConfig, api_group: ExabelApiGroup):
1315
self.config = config
1416
self.metadata = [("x-client-name", config.client_name)]
15-
host = api_group.get_host(config)
16-
port = api_group.get_port(config)
17+
common_kwargs = {
18+
"target": f"{api_group.get_host(config)}:{api_group.get_port(config)}",
19+
# When importing time series, we may receive a large amount of precondition failure
20+
# violations in the trailing metadata, therefore we increase the maximum metadata size.
21+
"options": (("grpc.max_metadata_size", SIXTEEN_MEGABYTES_IN_BYTES),),
22+
}
1723
if config.api_key == "NO_KEY":
1824
# Use an insecure channel. This can be used for local testing.
19-
self.channel = grpc.insecure_channel(host + ":" + str(port))
25+
self.channel = grpc.insecure_channel(**common_kwargs)
2026
else:
2127
assert config.api_key is not None
2228
self.metadata.append(("x-api-key", config.api_key))
2329
self.channel = grpc.secure_channel(
24-
host + ":" + str(port),
25-
grpc.ssl_channel_credentials(root_certificates=config.root_certificates),
30+
credentials=grpc.ssl_channel_credentials(
31+
root_certificates=config.root_certificates
32+
),
33+
**common_kwargs,
2634
)
2735
for header in self.config.extra_headers:
2836
self.metadata.append(header)
Lines changed: 67 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,67 @@
1+
from exabel_data_sdk.client.api.api_client.exabel_api_group import ExabelApiGroup
2+
from exabel_data_sdk.client.api.api_client.grpc.base_grpc_client import BaseGrpcClient
3+
from exabel_data_sdk.client.api.api_client.tag_api_client import TagApiClient
4+
from exabel_data_sdk.client.api.error_handler import handle_grpc_error
5+
from exabel_data_sdk.client.client_config import ClientConfig
6+
from exabel_data_sdk.stubs.exabel.api.analytics.v1.all_pb2 import (
7+
AddEntitiesRequest,
8+
AddEntitiesResponse,
9+
CreateTagRequest,
10+
DeleteTagRequest,
11+
GetTagRequest,
12+
ListTagEntitiesRequest,
13+
ListTagEntitiesResponse,
14+
ListTagsRequest,
15+
ListTagsResponse,
16+
RemoveEntitiesRequest,
17+
RemoveEntitiesResponse,
18+
Tag,
19+
UpdateTagRequest,
20+
)
21+
from exabel_data_sdk.stubs.exabel.api.analytics.v1.all_pb2_grpc import TagServiceStub
22+
23+
24+
class TagGrpcClient(TagApiClient, BaseGrpcClient):
25+
"""
26+
Client which sends tag requests to the Exabel Analytics API with gRPC.
27+
"""
28+
29+
def __init__(self, config: ClientConfig):
30+
super().__init__(config, ExabelApiGroup.ANALYTICS_API)
31+
self.stub = TagServiceStub(self.channel)
32+
33+
@handle_grpc_error
34+
def create_tag(self, request: CreateTagRequest) -> Tag:
35+
return self.stub.CreateTag(request, metadata=self.metadata, timeout=self.config.timeout)
36+
37+
@handle_grpc_error
38+
def get_tag(self, request: GetTagRequest) -> Tag:
39+
return self.stub.GetTag(request, metadata=self.metadata, timeout=self.config.timeout)
40+
41+
@handle_grpc_error
42+
def update_tag(self, request: UpdateTagRequest) -> Tag:
43+
return self.stub.UpdateTag(request, metadata=self.metadata, timeout=self.config.timeout)
44+
45+
@handle_grpc_error
46+
def delete_tag(self, request: DeleteTagRequest) -> None:
47+
return self.stub.DeleteTag(request, metadata=self.metadata, timeout=self.config.timeout)
48+
49+
@handle_grpc_error
50+
def list_tags(self, request: ListTagsRequest) -> ListTagsResponse:
51+
return self.stub.ListTags(request, metadata=self.metadata, timeout=self.config.timeout)
52+
53+
@handle_grpc_error
54+
def add_entities(self, request: AddEntitiesRequest) -> AddEntitiesResponse:
55+
return self.stub.AddEntities(request, metadata=self.metadata, timeout=self.config.timeout)
56+
57+
@handle_grpc_error
58+
def remove_entities(self, request: RemoveEntitiesRequest) -> RemoveEntitiesResponse:
59+
return self.stub.RemoveEntities(
60+
request, metadata=self.metadata, timeout=self.config.timeout
61+
)
62+
63+
@handle_grpc_error
64+
def list_entities(self, request: ListTagEntitiesRequest) -> ListTagEntitiesResponse:
65+
return self.stub.ListTagEntities(
66+
request, metadata=self.metadata, timeout=self.config.timeout
67+
)

exabel_data_sdk/client/api/api_client/grpc/time_series_grpc_client.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,8 @@
1717
)
1818
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2_grpc import TimeSeriesServiceStub
1919

20+
FIVE_MINUTES_IN_SECONDS = 5 * 60
21+
2022

2123
class TimeSeriesGrpcClient(TimeSeriesApiClient, BaseGrpcClient):
2224
"""
@@ -51,8 +53,12 @@ def update_time_series(self, request: UpdateTimeSeriesRequest) -> TimeSeries:
5153

5254
@handle_grpc_error
5355
def import_time_series(self, request: ImportTimeSeriesRequest) -> ImportTimeSeriesResponse:
56+
# Import requests at 1 MB can take a long time to complete, so we increase the timeout if
57+
# not already set to at least five minutes.
5458
return self.stub.ImportTimeSeries(
55-
request, metadata=self.metadata, timeout=self.config.timeout
59+
request,
60+
metadata=self.metadata,
61+
timeout=max(self.config.timeout, FIVE_MINUTES_IN_SECONDS),
5662
)
5763

5864
@handle_grpc_error
Lines changed: 55 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,55 @@
1+
from abc import ABC, abstractmethod
2+
3+
from exabel_data_sdk.stubs.exabel.api.analytics.v1.all_pb2 import (
4+
AddEntitiesRequest,
5+
AddEntitiesResponse,
6+
CreateTagRequest,
7+
DeleteTagRequest,
8+
GetTagRequest,
9+
ListTagEntitiesRequest,
10+
ListTagEntitiesResponse,
11+
ListTagsRequest,
12+
ListTagsResponse,
13+
RemoveEntitiesRequest,
14+
RemoveEntitiesResponse,
15+
Tag,
16+
UpdateTagRequest,
17+
)
18+
19+
20+
class TagApiClient(ABC):
21+
"""
22+
Superclass for clients that send tag requests to the Exabel Analytics API.
23+
"""
24+
25+
@abstractmethod
26+
def create_tag(self, request: CreateTagRequest) -> Tag:
27+
"""Create a tag."""
28+
29+
@abstractmethod
30+
def get_tag(self, request: GetTagRequest) -> Tag:
31+
"""Get a tag."""
32+
33+
@abstractmethod
34+
def update_tag(self, request: UpdateTagRequest) -> Tag:
35+
"""Update a tag."""
36+
37+
@abstractmethod
38+
def delete_tag(self, request: DeleteTagRequest) -> None:
39+
"""Delete a tag."""
40+
41+
@abstractmethod
42+
def list_tags(self, request: ListTagsRequest) -> ListTagsResponse:
43+
"""List all tags accessible to user."""
44+
45+
@abstractmethod
46+
def add_entities(self, request: AddEntitiesRequest) -> AddEntitiesResponse:
47+
"""Add entities to a tag."""
48+
49+
@abstractmethod
50+
def remove_entities(self, request: RemoveEntitiesRequest) -> RemoveEntitiesResponse:
51+
"""Remove entities from a tag."""
52+
53+
@abstractmethod
54+
def list_entities(self, request: ListTagEntitiesRequest) -> ListTagEntitiesResponse:
55+
"""List entities in a tag."""

0 commit comments

Comments
 (0)