Skip to content

Commit

Permalink
Return None instead of raising error for NotFound (#31)
Browse files Browse the repository at this point in the history
  • Loading branch information
hallarak authored Jul 2, 2021
1 parent 9dd2109 commit 0691a51
Show file tree
Hide file tree
Showing 8 changed files with 82 additions and 43 deletions.
32 changes: 20 additions & 12 deletions exabel_data_sdk/client/api/entity_api.py
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
from typing import Sequence
from typing import Optional, Sequence

from exabel_data_sdk.client.api.api_client.grpc.entity_grpc_client import EntityGrpcClient
from exabel_data_sdk.client.api.api_client.http.entity_http_client import EntityHttpClient
Expand Down Expand Up @@ -48,15 +48,22 @@ def list_entity_types(
total_size=response.total_size,
)

def get_entity_type(self, name: str) -> EntityType:
def get_entity_type(self, name: str) -> Optional[EntityType]:
"""
Get one entity type.
Return None if the entity type does not exist.
Args:
name: The resource name of the requested entity type, for example
"entityTypes/ns.type1".
"""
response = self.client.get_entity_type(GetEntityTypeRequest(name=name))
try:
response = self.client.get_entity_type(GetEntityTypeRequest(name=name))
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise
return EntityType.from_proto(response)

def list_entities(
Expand All @@ -81,15 +88,22 @@ def list_entities(
total_size=response.total_size,
)

def get_entity(self, name: str) -> Entity:
def get_entity(self, name: str) -> Optional[Entity]:
"""
Get one entity.
Return None if the entity does not exist.
Args:
name: The resource name of the requested entity, for example
"entityTypes/ns.type1/entities/ns.entity1".
"""
response = self.client.get_entity(GetEntityRequest(name=name))
try:
response = self.client.get_entity(GetEntityRequest(name=name))
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise
return Entity.from_proto(response)

def create_entity(self, entity: Entity, entity_type: str) -> Entity:
Expand Down Expand Up @@ -141,10 +155,4 @@ def entity_exists(self, name: str) -> bool:
name: The resource name of the entity,
for example "entityTypes/ns.type1/entities/ns.entity1".
"""
try:
self.get_entity(name)
return True
except RequestError as error:
if error.error_type is ErrorType.NOT_FOUND:
return False
raise
return self.get_entity(name) is not None
38 changes: 24 additions & 14 deletions exabel_data_sdk/client/api/relationship_api.py
Original file line number Diff line number Diff line change
@@ -1,3 +1,5 @@
from typing import Optional

from exabel_data_sdk.client.api.api_client.grpc.relationship_grpc_client import (
RelationshipGrpcClient,
)
Expand Down Expand Up @@ -49,15 +51,22 @@ def list_relationship_types(
total_size=response.total_size,
)

def get_relationship_type(self, name: str) -> RelationshipType:
def get_relationship_type(self, name: str) -> Optional[RelationshipType]:
"""
Get one relationship type.
Return None if the relationship type does not exist.
Args:
name: The resource name of the requested relationship type, for example
"relationshipTypes/ns.type1"
"""
response = self.client.get_relationship_type(GetRelationshipTypeRequest(name=name))
try:
response = self.client.get_relationship_type(GetRelationshipTypeRequest(name=name))
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise
return RelationshipType.from_proto(response)

def create_relationship_type(self, relationship_type: RelationshipType) -> RelationshipType:
Expand Down Expand Up @@ -153,10 +162,12 @@ def get_relationships_to_entity(

def get_relationship(
self, relationship_type: str, from_entity: str, to_entity: str
) -> Relationship:
) -> Optional[Relationship]:
"""
Get one relationship.
Return None if the relationship does not exist.
Args:
relationship_type: The type of the relationship, for example
"relationshipTypes/ns.type1".
Expand All @@ -165,11 +176,16 @@ def get_relationship(
to_entity: The resource name of the end point of the relationship, for example
"entityTypes/ns.type2/entities/ns.entity2".
"""
response = self.client.get_relationship(
GetRelationshipRequest(
parent=relationship_type, from_entity=from_entity, to_entity=to_entity
try:
response = self.client.get_relationship(
GetRelationshipRequest(
parent=relationship_type, from_entity=from_entity, to_entity=to_entity
)
)
)
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise
return Relationship.from_proto(response)

def create_relationship(self, relationship: Relationship) -> Relationship:
Expand Down Expand Up @@ -212,10 +228,4 @@ def relationship_exists(self, relationship_type: str, from_entity: str, to_entit
to_entity: The resource name of the end point of the relationship,
for example "entityTypes/ns.type2/entities/ns.entity2".
"""
try:
self.get_relationship(relationship_type, from_entity, to_entity)
return True
except RequestError as error:
if error.error_type is ErrorType.NOT_FOUND:
return False
raise
return self.get_relationship(relationship_type, from_entity, to_entity) is not None
18 changes: 14 additions & 4 deletions exabel_data_sdk/client/api/signal_api.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,9 @@
from typing import Optional

from exabel_data_sdk.client.api.api_client.grpc.signal_grpc_client import SignalGrpcClient
from exabel_data_sdk.client.api.api_client.http.signal_http_client import SignalHttpClient
from exabel_data_sdk.client.api.data_classes.paging_result import PagingResult
from exabel_data_sdk.client.api.data_classes.request_error import ErrorType, RequestError
from exabel_data_sdk.client.api.data_classes.signal import Signal
from exabel_data_sdk.client.client_config import ClientConfig
from exabel_data_sdk.stubs.exabel.api.data.v1.all_pb2 import (
Expand Down Expand Up @@ -37,16 +40,23 @@ def list_signals(self, page_size: int = 1000, page_token: str = None) -> PagingR
total_size=response.total_size,
)

def get_signal(self, name: str) -> Signal:
def get_signal(self, name: str) -> Optional[Signal]:
"""
Get one signal.
Return None if the signal does not exist.
Args:
name: The resource name of the requested signal, for example "signals/ns.signal1".
"""
response = self.client.get_signal(
GetSignalRequest(name=name),
)
try:
response = self.client.get_signal(
GetSignalRequest(name=name),
)
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise
return Signal.from_proto(response)

def create_signal(self, signal: Signal) -> Signal:
Expand Down
25 changes: 14 additions & 11 deletions exabel_data_sdk/client/api/time_series_api.py
Original file line number Diff line number Diff line change
Expand Up @@ -79,13 +79,15 @@ def get_entity_time_series(

def get_time_series(
self, name: str, start: pd.Timestamp = None, end: pd.Timestamp = None
) -> pd.Series:
) -> Optional[pd.Series]:
"""
Get one time series.
If start and end are not specified, all data points will be returned.
If start or end is specified, both must be specified.
If time series does not exist, None is returned.
Args:
name: The resource name of the requested time series, for example
"entityTypes/ns.type1/entities/ns.entity1/signals/ns.signal1" or
Expand All @@ -96,9 +98,16 @@ def get_time_series(
if bool(start) != bool(end):
raise ValueError("Either specify both 'start' and 'end' or none of them.")
time_range = self._get_time_range(start, end)
time_series = self.client.get_time_series(
GetTimeSeriesRequest(name=name, view=TimeSeriesView(time_range=time_range)),
)

try:
time_series = self.client.get_time_series(
GetTimeSeriesRequest(name=name, view=TimeSeriesView(time_range=time_range)),
)
except RequestError as error:
if error.error_type == ErrorType.NOT_FOUND:
return None
raise

return self._time_series_points_to_series(time_series.points, time_series.name)

def create_time_series(self, name: str, series: pd.Series) -> None:
Expand Down Expand Up @@ -205,13 +214,7 @@ def time_series_exists(self, name: str) -> bool:
name: The resource name of the time series, for example
"entityTypes/ns.type1/entities/ns.entity1/signals/ns.signal1".
"""
try:
self.get_time_series(name)
return True
except RequestError as error:
if error.error_type is ErrorType.NOT_FOUND:
return False
raise
return self.get_time_series(name) is not None

@staticmethod
def _series_to_time_series_points(series: pd.Series) -> Sequence[TimeSeriesPoint]:
Expand Down
1 change: 1 addition & 0 deletions exabel_data_sdk/examples/create_time_series_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -46,6 +46,7 @@ def create_time_series() -> None:

# Add a relationship between a company entity and the brand entity.
company_entity = client.entity_api.get_entity("entityTypes/company/entities/F_000Q07-E")
assert company_entity
relationship = client.relationship_api.create_relationship(
Relationship(
description="Relationship between a company and a brand.",
Expand Down
5 changes: 5 additions & 0 deletions exabel_data_sdk/examples/get_company_example.py
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,7 @@ def get_company() -> None:

# Fetch the company.
microsoft = client.entity_api.get_entity("entityTypes/company/entities/F_000Q07-E")
assert microsoft

# Retrieve location of company.
located_in_relationships = client.relationship_api.get_relationships_from_entity(
Expand All @@ -34,6 +35,7 @@ def get_company() -> None:
primary_security = client.entity_api.get_entity(
primary_security_relationships.results[0].to_entity
)
assert primary_security

# Retrieve primary regional for company.
primary_regional_relationships = client.relationship_api.get_relationships_from_entity(
Expand All @@ -43,6 +45,7 @@ def get_company() -> None:
primary_regional = client.entity_api.get_entity(
primary_regional_relationships.results[0].to_entity
)
assert primary_regional

# Retrieve primary listing for company.
primary_listing_relationships = client.relationship_api.get_relationships_from_entity(
Expand All @@ -61,6 +64,7 @@ def get_company() -> None:
# Retrieve all regionals.
regionals = []
for security in securities:
assert security
regional_relationships = client.relationship_api.get_relationships_from_entity(
relationship_type="relationshipTypes/HAS_REGIONAL", from_entity=security.name
)
Expand All @@ -71,6 +75,7 @@ def get_company() -> None:
# Retrieve all listings.
listings = []
for regional in regionals:
assert regional
listing_relationships = client.relationship_api.get_relationships_from_entity(
relationship_type="relationshipTypes/HAS_LISTING", from_entity=regional.name
)
Expand Down
4 changes: 3 additions & 1 deletion exabel_data_sdk/scripts/delete_entity.py
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,9 @@ def run_script(self, client: ExabelClient, args: argparse.Namespace) -> None:
print("Running dry-run...")

entity = client.entity_api.get_entity(args.entity_name)
if entity.read_only:
if entity is None:
print(f"Entity does not exist: {entity}")
elif entity.read_only:
print(f"ERROR: Entity is read-only: {entity}")
else:
if args.dry_run:
Expand Down
2 changes: 1 addition & 1 deletion setup.py
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,7 @@

setuptools.setup(
name="exabel-data-sdk",
version="0.0.14",
version="0.0.15",
author="Exabel",
author_email="[email protected]",
description="Python SDK for the Exabel Data API",
Expand Down

0 comments on commit 0691a51

Please sign in to comment.