Skip to content

Commit 7ee8f29

Browse files
committed
feat: add a generic API request interface
1 parent 7757ca1 commit 7ee8f29

File tree

3 files changed

+106
-5
lines changed

3 files changed

+106
-5
lines changed

easypost/easypost_client.py

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,11 +1,15 @@
1+
from typing import Any
2+
13
from easypost.constant import (
24
API_BASE,
35
API_VERSION,
46
INVALID_REQUESTS_VERSION_ERROR,
57
SUPPORT_EMAIL,
68
TIMEOUT,
79
)
10+
from easypost.easypost_object import convert_to_easypost_object
811
from easypost.hooks import RequestHook, ResponseHook
12+
from easypost.requestor import RequestMethod, Requestor
913
from easypost.services import (
1014
AddressService,
1115
ApiKeyService,
@@ -138,3 +142,14 @@ def subscribe_to_response_hook(self, function):
138142
def unsubscribe_from_response_hook(self, function):
139143
"""Unsubscribe functions from running when a response occurs."""
140144
self._response_hook -= function
145+
146+
def make_api_call(self, method: RequestMethod, endpoint: str, params: dict[str, Any]) -> dict[str, Any]:
147+
"""Make an API call to the EasyPost API.
148+
149+
This public, generic interface is useful for making arbitrary API calls to the EasyPost API that
150+
are not yet supported by the client library's services. When possible, the service for your use case
151+
should be used instead as it provides a more convenient and higher-level interface depending on the endpoint.
152+
"""
153+
response = Requestor(self).request(method=method, url=endpoint, params=params)
154+
155+
return convert_to_easypost_object(response=response)

tests/cassettes/test_client_make_api_call.yaml

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

tests/test_easypost_client.py

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -6,9 +6,10 @@
66

77
from easypost.easypost_client import EasyPostClient
88
from easypost.errors import TimeoutError
9+
from easypost.requestor import RequestMethod
910

1011

11-
def test_api_key():
12+
def test_easypost_client_api_key():
1213
"""Tests setting and getting API keys from different client objects."""
1314
client1 = EasyPostClient(api_key="123")
1415
assert client1.api_key == "123"
@@ -17,23 +18,23 @@ def test_api_key():
1718
assert client2.api_key == "456"
1819

1920

20-
def test_no_api_key():
21+
def test_easypost_client_no_api_key():
2122
"""Tests that we raise an error when no API key is passed to the client."""
2223
with pytest.raises(TypeError) as error:
2324
EasyPostClient()
2425

2526
assert "missing 1 required positional argument: 'api_key'" in str(error.value)
2627

2728

28-
def test_invalid_client_property():
29+
def test_easypost_client_invalid_client_property():
2930
"""Tests that we throw an error when attempting to use an invalid property of a client."""
3031
with pytest.raises(AttributeError) as error:
3132
EasyPostClient("123").invalid_property()
3233

3334
assert str(error.value) == "'EasyPostClient' object has no attribute 'invalid_property'"
3435

3536

36-
def test_api_base():
37+
def test_easypost_client_api_base():
3738
"""Tests that we can override the API base of the client object."""
3839
client1 = EasyPostClient(api_key="123")
3940
assert client1.api_base == "https://api.easypost.com/v2"
@@ -43,7 +44,7 @@ def test_api_base():
4344

4445

4546
@patch("requests.Session")
46-
def test_client_timeout(mock_session, basic_shipment):
47+
def test_easypost_client_timeout(mock_session, basic_shipment):
4748
"""Tests that the timeout gets used properly in requests when set."""
4849
mock_session().request.side_effect = requests.exceptions.Timeout()
4950
client = EasyPostClient(api_key=os.getenv("EASYPOST_TEST_API_KEY"), timeout=0.1)
@@ -53,3 +54,14 @@ def test_client_timeout(mock_session, basic_shipment):
5354
assert False
5455
except TimeoutError as error:
5556
assert error.message == "Request timed out."
57+
58+
59+
@pytest.mark.vcr()
60+
def test_client_make_api_call():
61+
"""Tests that we can make an API call using the generic make_api_call method."""
62+
client = EasyPostClient(api_key=os.getenv("EASYPOST_TEST_API_KEY"))
63+
64+
response = client.make_api_call(method=RequestMethod.GET, endpoint="/addresses", params={"page_size": 1})
65+
66+
assert len(response["addresses"]) == 1
67+
assert response["addresses"][0]["object"] == "Address"

0 commit comments

Comments
 (0)