-
Notifications
You must be signed in to change notification settings - Fork 12
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Support JSON requests over HTTP (#28)
- Loading branch information
Showing
43 changed files
with
1,433 additions
and
188 deletions.
There are no files selected for viewing
Empty file.
50 changes: 50 additions & 0 deletions
50
exabel_data_sdk/client/api/api_client/entity_api_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
from abc import ABC, abstractmethod | ||
|
||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import ( | ||
CreateEntityRequest, | ||
DeleteEntityRequest, | ||
Entity, | ||
EntityType, | ||
GetEntityRequest, | ||
GetEntityTypeRequest, | ||
ListEntitiesRequest, | ||
ListEntitiesResponse, | ||
ListEntityTypesRequest, | ||
ListEntityTypesResponse, | ||
SearchEntitiesRequest, | ||
SearchEntitiesResponse, | ||
) | ||
|
||
|
||
class EntityApiClient(ABC): | ||
""" | ||
Superclass for clients that send entity requests to the Exabel Data API. | ||
""" | ||
|
||
@abstractmethod | ||
def list_entity_types(self, request: ListEntityTypesRequest) -> ListEntityTypesResponse: | ||
"""List all known entity types.""" | ||
|
||
@abstractmethod | ||
def get_entity_type(self, request: GetEntityTypeRequest) -> EntityType: | ||
"""Get an entity type.""" | ||
|
||
@abstractmethod | ||
def list_entities(self, request: ListEntitiesRequest) -> ListEntitiesResponse: | ||
"""List all entities of a given entity type.""" | ||
|
||
@abstractmethod | ||
def get_entity(self, request: GetEntityRequest) -> Entity: | ||
"""Get an entity.""" | ||
|
||
@abstractmethod | ||
def create_entity(self, request: CreateEntityRequest) -> Entity: | ||
"""Create an entity.""" | ||
|
||
@abstractmethod | ||
def delete_entity(self, request: DeleteEntityRequest) -> None: | ||
"""Delete an entity.""" | ||
|
||
@abstractmethod | ||
def search_entities(self, request: SearchEntitiesRequest) -> SearchEntitiesResponse: | ||
"""Search for entities.""" |
Empty file.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
61 changes: 61 additions & 0 deletions
61
exabel_data_sdk/client/api/api_client/grpc/entity_grpc_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,61 @@ | ||
from exabel_data_sdk.client.api.api_client.entity_api_client import EntityApiClient | ||
from exabel_data_sdk.client.api.api_client.grpc.base_grpc_client import BaseGrpcClient | ||
from exabel_data_sdk.client.api.error_handler import handle_grpc_error | ||
from exabel_data_sdk.client.client_config import ClientConfig | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import ( | ||
CreateEntityRequest, | ||
DeleteEntityRequest, | ||
Entity, | ||
EntityType, | ||
GetEntityRequest, | ||
GetEntityTypeRequest, | ||
ListEntitiesRequest, | ||
ListEntitiesResponse, | ||
ListEntityTypesRequest, | ||
ListEntityTypesResponse, | ||
SearchEntitiesRequest, | ||
SearchEntitiesResponse, | ||
) | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2_grpc import EntityServiceStub | ||
|
||
|
||
class EntityGrpcClient(EntityApiClient, BaseGrpcClient): | ||
""" | ||
Client which sends entity requests to the Exabel Data API with gRPC. | ||
""" | ||
|
||
def __init__(self, config: ClientConfig): | ||
super().__init__(config) | ||
self.stub = EntityServiceStub(self.channel) | ||
|
||
@handle_grpc_error | ||
def list_entity_types(self, request: ListEntityTypesRequest) -> ListEntityTypesResponse: | ||
return self.stub.ListEntityTypes( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def get_entity_type(self, request: GetEntityTypeRequest) -> EntityType: | ||
return self.stub.GetEntityType(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def list_entities(self, request: ListEntitiesRequest) -> ListEntitiesResponse: | ||
return self.stub.ListEntities(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def get_entity(self, request: GetEntityRequest) -> Entity: | ||
return self.stub.GetEntity(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def create_entity(self, request: CreateEntityRequest) -> Entity: | ||
return self.stub.CreateEntity(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def delete_entity(self, request: DeleteEntityRequest) -> None: | ||
self.stub.DeleteEntity(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def search_entities(self, request: SearchEntitiesRequest) -> SearchEntitiesResponse: | ||
return self.stub.SearchEntities( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) |
77 changes: 77 additions & 0 deletions
77
exabel_data_sdk/client/api/api_client/grpc/relationship_grpc_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,77 @@ | ||
from exabel_data_sdk.client.api.api_client.grpc.base_grpc_client import BaseGrpcClient | ||
from exabel_data_sdk.client.api.api_client.relationship_api_client import RelationshipApiClient | ||
from exabel_data_sdk.client.api.error_handler import handle_grpc_error | ||
from exabel_data_sdk.client.client_config import ClientConfig | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import ( | ||
CreateRelationshipRequest, | ||
CreateRelationshipTypeRequest, | ||
DeleteRelationshipRequest, | ||
DeleteRelationshipTypeRequest, | ||
GetRelationshipRequest, | ||
GetRelationshipTypeRequest, | ||
ListRelationshipsRequest, | ||
ListRelationshipsResponse, | ||
ListRelationshipTypesRequest, | ||
ListRelationshipTypesResponse, | ||
Relationship, | ||
RelationshipType, | ||
) | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2_grpc import RelationshipServiceStub | ||
|
||
|
||
class RelationshipGrpcClient(RelationshipApiClient, BaseGrpcClient): | ||
""" | ||
Client which sends relationship requests to the Exabel Data API with gRPC. | ||
""" | ||
|
||
def __init__(self, config: ClientConfig): | ||
super().__init__(config) | ||
self.stub = RelationshipServiceStub(self.channel) | ||
|
||
@handle_grpc_error | ||
def list_relationship_types( | ||
self, request: ListRelationshipTypesRequest | ||
) -> ListRelationshipTypesResponse: | ||
return self.stub.ListRelationshipTypes( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def get_relationship_type(self, request: GetRelationshipTypeRequest) -> RelationshipType: | ||
return self.stub.GetRelationshipType( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def create_relationship_type(self, request: CreateRelationshipTypeRequest) -> RelationshipType: | ||
return self.stub.CreateRelationshipType( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def delete_relationship_type(self, request: DeleteRelationshipTypeRequest) -> None: | ||
return self.stub.DeleteRelationshipType( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def list_relationships(self, request: ListRelationshipsRequest) -> ListRelationshipsResponse: | ||
return self.stub.ListRelationships( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def get_relationship(self, request: GetRelationshipRequest) -> Relationship: | ||
return self.stub.GetRelationship( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def create_relationship(self, request: CreateRelationshipRequest) -> Relationship: | ||
return self.stub.CreateRelationship( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def delete_relationship(self, request: DeleteRelationshipRequest) -> None: | ||
self.stub.DeleteRelationship(request, metadata=self.metadata, timeout=self.config.timeout) |
55 changes: 55 additions & 0 deletions
55
exabel_data_sdk/client/api/api_client/grpc/signal_grpc_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,55 @@ | ||
from exabel_data_sdk.client.api.api_client.grpc.base_grpc_client import BaseGrpcClient | ||
from exabel_data_sdk.client.api.api_client.signal_api_client import SignalApiClient | ||
from exabel_data_sdk.client.api.error_handler import handle_grpc_error | ||
from exabel_data_sdk.client.client_config import ClientConfig | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import ( | ||
CreateSignalRequest, | ||
DeleteSignalRequest, | ||
GetSignalRequest, | ||
ListSignalsRequest, | ||
ListSignalsResponse, | ||
Signal, | ||
) | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2_grpc import SignalServiceStub | ||
|
||
|
||
class SignalGrpcClient(SignalApiClient, BaseGrpcClient): | ||
""" | ||
Client which sends signal requests to the Exabel Data API with gRPC. | ||
""" | ||
|
||
def __init__(self, config: ClientConfig): | ||
super().__init__(config) | ||
self.stub = SignalServiceStub(self.channel) | ||
|
||
@handle_grpc_error | ||
def list_signals(self, request: ListSignalsRequest) -> ListSignalsResponse: | ||
return self.stub.ListSignals( | ||
request, | ||
metadata=self.metadata, | ||
timeout=self.config.timeout, | ||
) | ||
|
||
@handle_grpc_error | ||
def get_signal(self, request: GetSignalRequest) -> Signal: | ||
return self.stub.GetSignal( | ||
request, | ||
metadata=self.metadata, | ||
timeout=self.config.timeout, | ||
) | ||
|
||
@handle_grpc_error | ||
def create_signal(self, request: CreateSignalRequest) -> Signal: | ||
return self.stub.CreateSignal( | ||
request, | ||
metadata=self.metadata, | ||
timeout=self.config.timeout, | ||
) | ||
|
||
@handle_grpc_error | ||
def delete_signal(self, request: DeleteSignalRequest) -> None: | ||
self.stub.DeleteSignal( | ||
request, | ||
metadata=self.metadata, | ||
timeout=self.config.timeout, | ||
) |
57 changes: 57 additions & 0 deletions
57
exabel_data_sdk/client/api/api_client/grpc/time_series_grpc_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,57 @@ | ||
from exabel_data_sdk.client.api.api_client.grpc.base_grpc_client import BaseGrpcClient | ||
from exabel_data_sdk.client.api.api_client.time_series_api_client import TimeSeriesApiClient | ||
from exabel_data_sdk.client.api.error_handler import handle_grpc_error | ||
from exabel_data_sdk.client.client_config import ClientConfig | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import ( | ||
BatchDeleteTimeSeriesPointsRequest, | ||
CreateTimeSeriesRequest, | ||
DeleteTimeSeriesRequest, | ||
GetTimeSeriesRequest, | ||
ListTimeSeriesRequest, | ||
ListTimeSeriesResponse, | ||
TimeSeries, | ||
UpdateTimeSeriesRequest, | ||
) | ||
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2_grpc import TimeSeriesServiceStub | ||
|
||
|
||
class TimeSeriesGrpcClient(TimeSeriesApiClient, BaseGrpcClient): | ||
""" | ||
Client which sends time series requests to the Exabel Data API with gRPC. | ||
""" | ||
|
||
def __init__(self, config: ClientConfig): | ||
super().__init__(config) | ||
self.stub = TimeSeriesServiceStub(self.channel) | ||
|
||
@handle_grpc_error | ||
def list_time_series(self, request: ListTimeSeriesRequest) -> ListTimeSeriesResponse: | ||
return self.stub.ListTimeSeries( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def get_time_series(self, request: GetTimeSeriesRequest) -> TimeSeries: | ||
return self.stub.GetTimeSeries(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def create_time_series(self, request: CreateTimeSeriesRequest) -> TimeSeries: | ||
return self.stub.CreateTimeSeries( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def update_time_series(self, request: UpdateTimeSeriesRequest) -> TimeSeries: | ||
return self.stub.UpdateTimeSeries( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) | ||
|
||
@handle_grpc_error | ||
def delete_time_series(self, request: DeleteTimeSeriesRequest) -> None: | ||
self.stub.DeleteTimeSeries(request, metadata=self.metadata, timeout=self.config.timeout) | ||
|
||
@handle_grpc_error | ||
def batch_delete_time_series_points(self, request: BatchDeleteTimeSeriesPointsRequest) -> None: | ||
self.stub.BatchDeleteTimeSeriesPoints( | ||
request, metadata=self.metadata, timeout=self.config.timeout | ||
) |
Empty file.
50 changes: 50 additions & 0 deletions
50
exabel_data_sdk/client/api/api_client/http/base_http_client.py
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
import json | ||
from typing import Optional, TypeVar, overload | ||
|
||
import requests | ||
from google.protobuf.json_format import MessageToJson, Parse | ||
from google.protobuf.message import Message | ||
|
||
from exabel_data_sdk.client.api.data_classes.request_error import RequestError | ||
from exabel_data_sdk.client.api.error_handler import http_status_to_error_type | ||
from exabel_data_sdk.client.client_config import ClientConfig | ||
|
||
TMessage = TypeVar("TMessage", bound=Message) | ||
|
||
|
||
class BaseHttpClient: | ||
""" | ||
Base class for clients that access the Exabel Data API with JSON over HTTP. | ||
""" | ||
|
||
def __init__(self, config: ClientConfig): | ||
self.config = config | ||
|
||
@overload | ||
def _request( | ||
self, method: str, url: str, response_proto: TMessage, body: Message = None | ||
) -> TMessage: | ||
... | ||
|
||
@overload | ||
def _request(self, method: str, url: str, response_proto: None, body: Message = None) -> None: | ||
... | ||
|
||
def _request( | ||
self, method: str, url: str, response_proto: Optional[TMessage], body: Message = None | ||
) -> Optional[TMessage]: | ||
response = requests.request( | ||
method, | ||
f"https://{self.config.host}/v1/{url}", | ||
data=MessageToJson(body) if body is not None else None, | ||
headers={ | ||
"Accept": "application/json", | ||
"X-Api-Key": self.config.api_key, | ||
}, | ||
) | ||
if response.status_code != 200: | ||
values = json.loads(response.content) | ||
raise RequestError(http_status_to_error_type(response.status_code), values["message"]) | ||
if response_proto is None: | ||
return None | ||
return Parse(response.content, response_proto) |
Oops, something went wrong.