From 26ea1c227c140e2a3046d8f90712c730f8d1cf96 Mon Sep 17 00:00:00 2001 From: Christopher Burgess Date: Fri, 29 Nov 2019 17:30:36 +0000 Subject: [PATCH 1/2] fix: Reference now returns dict, fixes #69 --- tests/conversions/test_conversions.py | 2 +- tests/endpoints/test_products_real.py | 2 +- tests/mock_client.py | 5 +++-- vortexasdk/client.py | 4 ++-- vortexasdk/endpoints/corporations.py | 2 +- vortexasdk/endpoints/geographies.py | 2 +- vortexasdk/endpoints/products.py | 2 +- vortexasdk/endpoints/vessels.py | 2 +- vortexasdk/exceptions.py | 4 ++++ vortexasdk/operations.py | 14 ++++++++++++-- 10 files changed, 27 insertions(+), 12 deletions(-) create mode 100644 vortexasdk/exceptions.py diff --git a/tests/conversions/test_conversions.py b/tests/conversions/test_conversions.py index 3ce30615..6ee63255 100644 --- a/tests/conversions/test_conversions.py +++ b/tests/conversions/test_conversions.py @@ -12,7 +12,7 @@ def test_convert_to_geography_ids(self): rotterdam_id = ( "68faf65af1345067f11dc6723b8da32f00e304a6f33c000118fccd81947deb4e" ) - rotterdam_name = Geographies().reference(rotterdam_id)[0]["name"] + rotterdam_name = Geographies().reference(rotterdam_id)["name"] result = convert_to_geography_ids([rotterdam_name]) diff --git a/tests/endpoints/test_products_real.py b/tests/endpoints/test_products_real.py index c9c1a0aa..1eb4c63c 100644 --- a/tests/endpoints/test_products_real.py +++ b/tests/endpoints/test_products_real.py @@ -75,4 +75,4 @@ def test_lookup_crude(self): "6f11b0724c9a4e85ffa7f1445bc768f054af755a090118dcf99f14745c261653" ) - assert result[0]["name"] == "Crude" + assert result["name"] == "Crude" diff --git a/tests/mock_client.py b/tests/mock_client.py index 6e899252..92604dea 100644 --- a/tests/mock_client.py +++ b/tests/mock_client.py @@ -32,8 +32,9 @@ class MockVortexaClient(AbstractVortexaClient): VESSEL_MOVEMENTS_RESOURCE: example_vessel_movements, } - def get_reference(self, resource: str, id: ID) -> str: - return "" + def get_reference(self, resource: str, id: ID) -> List[Dict]: + entities = MockVortexaClient._results[resource] + return [e for e in entities if e["id"] == id] def search(self, resource: str, **data) -> List: return MockVortexaClient._results[resource] diff --git a/vortexasdk/client.py b/vortexasdk/client.py index d30d0736..7c8a67bd 100644 --- a/vortexasdk/client.py +++ b/vortexasdk/client.py @@ -2,7 +2,7 @@ import functools import os from multiprocessing.pool import ThreadPool -from typing import List +from typing import List, Dict from requests import Response @@ -23,7 +23,7 @@ class VortexaClient(AbstractVortexaClient): def __init__(self, **kwargs): self.api_key = kwargs["api_key"] - def get_reference(self, resource: str, id: ID) -> str: + def get_reference(self, resource: str, id: ID) -> List[Dict]: """Lookup reference data.""" url = self._create_url(f"{resource}/{id}") response = retry_get(url) diff --git a/vortexasdk/endpoints/corporations.py b/vortexasdk/endpoints/corporations.py index 19e6d86d..5eaf33d1 100644 --- a/vortexasdk/endpoints/corporations.py +++ b/vortexasdk/endpoints/corporations.py @@ -55,7 +55,7 @@ def search(self, term: Union[str, List[str]] = None) -> CorporationsResult: params = convert_values_to_list({"term": term}) return CorporationsResult(super().search(**params)) - def reference(self, id: ID): + def reference(self, id: ID) -> dict: """ Perform a corporation lookup. diff --git a/vortexasdk/endpoints/geographies.py b/vortexasdk/endpoints/geographies.py index 0aadc77f..2b2b6534 100644 --- a/vortexasdk/endpoints/geographies.py +++ b/vortexasdk/endpoints/geographies.py @@ -51,7 +51,7 @@ def search(self, term: Union[str, List[str]]) -> GeographyResult: params = convert_values_to_list({"term": term}) return GeographyResult(super().search(**params)) - def reference(self, id: ID): + def reference(self, id: ID) -> dict: """ Perform a geography lookup. diff --git a/vortexasdk/endpoints/products.py b/vortexasdk/endpoints/products.py index db75c8df..5ea02663 100644 --- a/vortexasdk/endpoints/products.py +++ b/vortexasdk/endpoints/products.py @@ -67,7 +67,7 @@ def search( return ProductResult(super().search(**search_params)) - def reference(self, id: ID): + def reference(self, id: ID) -> dict: """ Perform a product lookup. diff --git a/vortexasdk/endpoints/vessels.py b/vortexasdk/endpoints/vessels.py index ac2bd23c..0bdb081f 100644 --- a/vortexasdk/endpoints/vessels.py +++ b/vortexasdk/endpoints/vessels.py @@ -85,7 +85,7 @@ def search( return VesselsResult(super().search(**search_params)) - def reference(self, id: ID): + def reference(self, id: ID) -> dict: """ Perform a vessel lookup. diff --git a/vortexasdk/exceptions.py b/vortexasdk/exceptions.py new file mode 100644 index 00000000..380255ba --- /dev/null +++ b/vortexasdk/exceptions.py @@ -0,0 +1,4 @@ +class InvalidAPIDataResponseException(Exception): + """Vortexa API returned Faulty Data, contact support.""" + + pass diff --git a/vortexasdk/operations.py b/vortexasdk/operations.py index af523bfb..a9e6932e 100644 --- a/vortexasdk/operations.py +++ b/vortexasdk/operations.py @@ -2,6 +2,7 @@ from vortexasdk.api.id import ID from vortexasdk.client import default_client +from vortexasdk.exceptions import InvalidAPIDataResponseException from vortexasdk.logger import get_logger logger = get_logger(__name__) @@ -20,7 +21,7 @@ def __init__(self, resource): """ self._resource = resource - def reference(self, id: ID): + def reference(self, id: ID) -> dict: """ Lookup reference data using ID. @@ -38,7 +39,16 @@ def reference(self, id: ID): logger.info( f"Looking up {self.__class__.__name__} reference data with id: {id}" ) - return default_client().get_reference(self._resource, id) + + data = default_client().get_reference(self._resource, id) + + assert len(data) <= 1, InvalidAPIDataResponseException( + f"Server error: more than one record returned matching ID {id}" + ) + try: + return data[0] + except IndexError: + return {} class Search: From d5583b8586424e4b2da9173e9f6aaeec80989368 Mon Sep 17 00:00:00 2001 From: Christopher Burgess Date: Fri, 29 Nov 2019 18:00:54 +0000 Subject: [PATCH 2/2] refactor: Make dict->Dict typing suggestions from @paddyroddy --- .../endpoints/test_reference_endpoints_real.py | 18 ++++++++++++++++++ vortexasdk/client.py | 4 ++-- vortexasdk/endpoints/corporations.py | 4 ++-- vortexasdk/endpoints/geographies.py | 4 ++-- vortexasdk/endpoints/products.py | 4 ++-- vortexasdk/endpoints/vessels.py | 4 ++-- vortexasdk/operations.py | 4 ++-- 7 files changed, 30 insertions(+), 12 deletions(-) create mode 100644 tests/endpoints/test_reference_endpoints_real.py diff --git a/tests/endpoints/test_reference_endpoints_real.py b/tests/endpoints/test_reference_endpoints_real.py new file mode 100644 index 00000000..d34c0384 --- /dev/null +++ b/tests/endpoints/test_reference_endpoints_real.py @@ -0,0 +1,18 @@ +from tests.testcases import TestCaseUsingRealAPI +from docs.utils import to_markdown +from vortexasdk import Geographies + + +class TestGeographiesReal(TestCaseUsingRealAPI): + def test_search(self): + geographies = Geographies().search(term=["Liverpool", "Southampton"]) + names = [g["name"] for g in geographies] + + assert "Liverpool [GB]" in names + + def test_search_to_df(self): + geographies = ( + Geographies().search(term=["Liverpool", "Southampton"]).to_df() + ) + + print(to_markdown(geographies)) diff --git a/vortexasdk/client.py b/vortexasdk/client.py index 7c8a67bd..ebbacc05 100644 --- a/vortexasdk/client.py +++ b/vortexasdk/client.py @@ -2,7 +2,7 @@ import functools import os from multiprocessing.pool import ThreadPool -from typing import List, Dict +from typing import Dict, List from requests import Response @@ -91,7 +91,7 @@ def _send_post_request(url, payload, size, offset): return response -def _handle_response(response: Response, payload=None) -> dict: +def _handle_response(response: Response, payload=None) -> Dict: if response.ok: return response.json() else: diff --git a/vortexasdk/endpoints/corporations.py b/vortexasdk/endpoints/corporations.py index 5eaf33d1..a3823e3f 100644 --- a/vortexasdk/endpoints/corporations.py +++ b/vortexasdk/endpoints/corporations.py @@ -1,5 +1,5 @@ """Corporations Endpoint.""" -from typing import List, Union +from typing import List, Union, Dict from vortexasdk.api import ID from vortexasdk.endpoints.corporations_result import CorporationsResult @@ -55,7 +55,7 @@ def search(self, term: Union[str, List[str]] = None) -> CorporationsResult: params = convert_values_to_list({"term": term}) return CorporationsResult(super().search(**params)) - def reference(self, id: ID) -> dict: + def reference(self, id: ID) -> Dict: """ Perform a corporation lookup. diff --git a/vortexasdk/endpoints/geographies.py b/vortexasdk/endpoints/geographies.py index 2b2b6534..daee6357 100644 --- a/vortexasdk/endpoints/geographies.py +++ b/vortexasdk/endpoints/geographies.py @@ -1,5 +1,5 @@ """Geographies Endpoint.""" -from typing import List, Union +from typing import List, Union, Dict from vortexasdk.api import ID from vortexasdk.endpoints.endpoints import GEOGRAPHIES_REFERENCE @@ -51,7 +51,7 @@ def search(self, term: Union[str, List[str]]) -> GeographyResult: params = convert_values_to_list({"term": term}) return GeographyResult(super().search(**params)) - def reference(self, id: ID) -> dict: + def reference(self, id: ID) -> Dict: """ Perform a geography lookup. diff --git a/vortexasdk/endpoints/products.py b/vortexasdk/endpoints/products.py index 5ea02663..58f6fe22 100644 --- a/vortexasdk/endpoints/products.py +++ b/vortexasdk/endpoints/products.py @@ -1,5 +1,5 @@ """Products Endpoint.""" -from typing import List, Union +from typing import List, Union, Dict from vortexasdk.api.shared_types import ID from vortexasdk.endpoints.endpoints import PRODUCTS_REFERENCE @@ -67,7 +67,7 @@ def search( return ProductResult(super().search(**search_params)) - def reference(self, id: ID) -> dict: + def reference(self, id: ID) -> Dict: """ Perform a product lookup. diff --git a/vortexasdk/endpoints/vessels.py b/vortexasdk/endpoints/vessels.py index 0bdb081f..ffde9a9f 100644 --- a/vortexasdk/endpoints/vessels.py +++ b/vortexasdk/endpoints/vessels.py @@ -1,5 +1,5 @@ """Vessels Endpoint.""" -from typing import List, Union +from typing import List, Union, Dict from vortexasdk.api.id import ID from vortexasdk.conversions import convert_to_product_ids @@ -85,7 +85,7 @@ def search( return VesselsResult(super().search(**search_params)) - def reference(self, id: ID) -> dict: + def reference(self, id: ID) -> Dict: """ Perform a vessel lookup. diff --git a/vortexasdk/operations.py b/vortexasdk/operations.py index a9e6932e..efb5efab 100644 --- a/vortexasdk/operations.py +++ b/vortexasdk/operations.py @@ -1,4 +1,4 @@ -from typing import List +from typing import Dict, List from vortexasdk.api.id import ID from vortexasdk.client import default_client @@ -21,7 +21,7 @@ def __init__(self, resource): """ self._resource = resource - def reference(self, id: ID) -> dict: + def reference(self, id: ID) -> Dict: """ Lookup reference data using ID.