diff --git a/README.md b/README.md index f695d8b..a355df4 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,7 @@ This package contains common Python utility classes and functions. * Connecting to and querying a PostgreSQL database using a connection pool * Connecting to and querying Redshift * Making requests to the Oauth2 authenticated APIs such as NYPL Platform API and Sierra +* Interacting with vendor APIs such as cloudLibrary ## Functions * Reading a YAML config file and putting the contents in os.environ -- see `config/sample.yaml` for an example of how the config file should be formatted diff --git a/src/nypl_py_utils/classes/cloudlibrary_client.py b/src/nypl_py_utils/classes/cloudlibrary_client.py index e5bc57b..dcc4524 100644 --- a/src/nypl_py_utils/classes/cloudlibrary_client.py +++ b/src/nypl_py_utils/classes/cloudlibrary_client.py @@ -30,9 +30,10 @@ def setup_session(self): self.session.mount("https://", HTTPAdapter(max_retries=retry_policy)) - def get_library_events(self, start_date=None, end_date=None) -> requests.Response: + def get_library_events(self, start_date=None, + end_date=None) -> requests.Response: """ - Retrieves all the events related to library-owned items within the + Retrieves all the events related to library-owned items within the optional timeframe. Pulls yesterday's events by default. start_date and end_date are optional parameters, and must be @@ -47,32 +48,36 @@ def get_library_events(self, start_date=None, end_date=None) -> requests.Respons today, date_format) if end_date is None else end_date if start_date > end_date: - error_message = f"Start date {start_date} is greater than end date {end_date}, cannot retrieve library events" + error_message = (f"Start date {start_date} greater than end date " + f"{end_date}, cannot retrieve library events") self.logger.error(error_message) raise CloudLibraryClientError(error_message) self.logger.info( - f"Fetching all library events in time frame {start_date} to {end_date}...") + (f"Fetching all library events in " + f"time frame {start_date} to {end_date}...")) path = f"data/cloudevents?startdate={start_date}&enddate={end_date}" response = self.request(path=path, method_type="GET") return response - def create_request_body(self, request_type, item_id, patron_id) -> str: + def create_request_body(self, request_type, + item_id, patron_id) -> str: """ - Helper function to generate request body when performing item - and/or patron-specific functions (ex. checking out a title). + Helper function to generate request body when performing item + and/or patron-specific functions (ex. checking out a title). """ - request_template = "<%(request_type)s>%(item_id)s%(patron_id)s" + request_template = "<%(request_type)s>%(item_id)s%(patron_id)s" # noqa return request_template % { "request_type": request_type, "item_id": item_id, "patron_id": patron_id, } - def request(self, path, method_type="POST", body=None) -> requests.Response: + def request(self, path, method_type="POST", + body=None) -> requests.Response: """ - Use this method to call specific paths in the cloudLibrary API. + Use this method to call specific paths in the cloudLibrary API. This method is necessary for building headers/authorization. Example usage of this method is in the get_library_events function. """ @@ -121,7 +126,8 @@ def _build_headers(self, method_type, path) -> dict: return headers - def _build_authorization(self, method_type, path) -> tuple[str, str]: + def _build_authorization(self, method_type, + path) -> tuple[str, str]: now = datetime.now(timezone.utc).strftime( "%a, %d %b %Y %H:%M:%S GMT") message = "\n".join([now, method_type, path]) diff --git a/tests/test_cloudlibrary_client.py b/tests/test_cloudlibrary_client.py index db4fc81..786c17c 100644 --- a/tests/test_cloudlibrary_client.py +++ b/tests/test_cloudlibrary_client.py @@ -1,34 +1,33 @@ import pytest from freezegun import freeze_time -from unittest import mock - from requests import ConnectTimeout -from nypl_py_utils.classes.cloudlibrary_client import CloudLibraryClient, CloudLibraryClientError +from nypl_py_utils.classes.cloudlibrary_client import ( + CloudLibraryClient, CloudLibraryClientError) _API_URL = "https://partner.yourcloudlibrary.com/cirrus/library/" # catch-all API response since we're not testing actual data _TEST_LIBRARY_EVENTS_RESPONSE = """ - 4302fcca-ef99-49bf-bd29-d673e990f765 - 2024-11-10T17:35:18 - 2012-11-11T13:58:52.055 - - - 4302fcca-ef99-49bf-bd29-d673e990f4a7 - CHECKIN - 2024-11-10T05:07:56 - 2024-11-10T07:50:59 - edbz9 - 1234 - 9780307238405 - TestUser1 - 1234 - 2024-11-10T17:35:18 - - +xmlns:xsd="http://www.w3.org/2001/XMLSchema" +xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"> +4302fcca-ef99-49bf-bd29-d673e990f765 +2024-11-10T17:35:18 +2012-11-11T13:58:52.055 + + +4302fcca-ef99-49bf-bd29-d673e990f4a7 +CHECKIN +2024-11-10T05:07:56 +2024-11-10T07:50:59 +edbz9 +1234 +9780307238405 +TestUser1 +1234 +2024-11-10T17:35:18 + + """ @@ -40,52 +39,60 @@ def test_instance(self): return CloudLibraryClient( "library_id", "account_id", "account_key") - def test_get_library_events_success_no_args(self, test_instance, requests_mock, caplog): + def test_get_library_events_success_no_args( + self, test_instance, requests_mock, caplog): start = "2024-11-10T10:00:00" end = "2024-11-11T10:00:00" requests_mock.get( - f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", + f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", # noqa text=_TEST_LIBRARY_EVENTS_RESPONSE) response = test_instance.get_library_events() assert response.text == _TEST_LIBRARY_EVENTS_RESPONSE - assert f"Fetching all library events in time frame {start} to {end}..." in caplog.text + assert (f"Fetching all library events in time frame " + f"{start} to {end}...") in caplog.text - def test_get_library_events_success_with_start_and_end_date(self, test_instance, requests_mock, caplog): + def test_get_library_events_success_with_start_and_end_date( + self, test_instance, requests_mock, caplog): start = "2024-11-01T10:00:00" end = "2024-11-05T10:00:00" requests_mock.get( - f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", + f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", # noqa text=_TEST_LIBRARY_EVENTS_RESPONSE) response = test_instance.get_library_events(start, end) assert response.text == _TEST_LIBRARY_EVENTS_RESPONSE - assert f"Fetching all library events in time frame {start} to {end}..." in caplog.text + assert (f"Fetching all library events in time frame " + f"{start} to {end}...") in caplog.text - def test_get_library_events_success_with_no_end_date(self, test_instance, requests_mock, caplog): + def test_get_library_events_success_with_no_end_date( + self, test_instance, requests_mock, caplog): start = "2024-11-01T09:00:00" end = "2024-11-11T10:00:00" requests_mock.get( - f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", + f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", # noqa text=_TEST_LIBRARY_EVENTS_RESPONSE) response = test_instance.get_library_events(start) assert response.text == _TEST_LIBRARY_EVENTS_RESPONSE - assert f"Fetching all library events in time frame {start} to {end}..." in caplog.text + assert (f"Fetching all library events in time frame " + f"{start} to {end}...") in caplog.text - def test_get_library_events_exception_when_start_date_greater_than_end(self, test_instance, caplog): + def test_get_library_events_exception_when_start_date_greater_than_end( + self, test_instance, caplog): start = "2024-11-11T09:00:00" end = "2024-11-01T10:00:00" with pytest.raises(CloudLibraryClientError): test_instance.get_library_events(start, end) - assert f"Start date {start} is greater than end date {end}, cannot retrieve library events" in caplog.text + assert (f"Start date {start} greater than end date " + f"{end}, cannot retrieve library events") in caplog.text def test_get_library_events_failure(self, test_instance, requests_mock): start = "2024-11-10T10:00:00" end = "2024-11-11T10:00:00" requests_mock.get( - f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", + f"{_API_URL}{test_instance.library_id}/data/cloudevents?startdate={start}&enddate={end}", # noqa exc=ConnectTimeout) with pytest.raises(CloudLibraryClientError): @@ -95,7 +102,9 @@ def test_create_request_body_success(self, test_instance): request_type = "CheckoutRequest" item_id = "df45qw" patron_id = "215555602845" - EXPECTED_REQUEST_BODY = f"<{request_type}>{item_id}{patron_id}" + EXPECTED_REQUEST_BODY = (f"<{request_type}>{item_id}" + f"{patron_id}" + f"") request_body = test_instance.create_request_body( request_type, item_id, patron_id)