Skip to content

Commit a53610a

Browse files
authored
Merge pull request #281 from EasyPost/v8_upgrade_guide
docs: adds v8 upgrade guide
2 parents d79b29e + cd553e0 commit a53610a

File tree

7 files changed

+146
-21
lines changed

7 files changed

+146
-21
lines changed

CHANGELOG.md

Lines changed: 11 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -1,15 +1,19 @@
11
# CHANGELOG
22

3-
## Next Major Release
3+
## v8.0.0 (2023-05-22)
44

5-
- New client object
6-
- Services and models
5+
- New `EasyPostClient` object
6+
- Logic is grouped together in Services and each EasyPost object has a new model (eg: `client.shipment.create()`)
7+
- Error handling overhaul
8+
- Introduces ~2 dozen new error types that extend from either `ApiError` or `EasyPostError`
9+
- ApiErrors behave like the previous `Error` class did. They will include a `message`, `http_status`, and `http_body`. Additionally, a new `code` and `errors` keys are present and populate when available
710
- Beta namespace changed from `easypost.beta.x` to `client.beta_x`
811
- Empty API response functions return `None` instead of `True`
9-
- References to `Referral` are now `ReferralCustomer` and `referral_customer` to match the API and docs
10-
- References to `Smartrate` are now `SmartRate` and `smart_rate` to match the API and docs
11-
- References to `Scanform` are now `ScanForm` and `scan_form`
12-
- `primary_or_secondary` paramater name for billing functions is now called `priority` to match the API and docs
12+
- Corrected naming conventions
13+
- References to `Referral` are now `ReferralCustomer` and `referral_customer` to match the API and docs
14+
- References to `Smartrate` are now `SmartRate` and `smart_rate` to match the API and docs
15+
- References to `Scanform` are now `ScanForm` and `scan_form`
16+
- `primary_or_secondary` paramater name for billing functions is now called `priority` to match the API and docs
1317
- The `update_email` function of the `referral_customer` service had the parameter order switched so `id` (previously called `user_id`) is first which matches the rest of the library
1418
- Dropped Python 3.6 support
1519
- Bumps all dependencies

README.md

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -27,9 +27,9 @@ A simple create & buy shipment example:
2727
import os
2828
import easypost
2929

30-
easypost.api_key = os.getenv('EASYPOST_API_KEY')
30+
client = easypost.EasyPostClient(os.getenv('EASYPOST_API_KEY'))
3131

32-
shipment = easypost.Shipment.create(
32+
shipment = client.shipment.create(
3333
from_address = {
3434
"name": "EasyPost",
3535
"street1": "118 2nd Street",
@@ -57,9 +57,9 @@ shipment = easypost.Shipment.create(
5757
},
5858
)
5959

60-
shipment.buy(rate=shipment.lowest_rate())
60+
bought_shipment = client.shipment.buy(shipment.id, rate=shipment.lowest_rate())
6161

62-
print(shipment)
62+
print(bought_shipment)
6363
```
6464

6565
## Documentation

UPGRADE_GUIDE.md

Lines changed: 121 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -2,11 +2,132 @@
22

33
Use the following guide to assist in the upgrade process of the `easypost-python` library between major versions.
44

5+
- [Upgrading from 7.x to 8.0](#upgrading-from-7x-to-80)
56
- [Upgrading from 6.x to 7.0](#upgrading-from-6x-to-70)
67
- [Upgrading from 5.x to 6.0](#upgrading-from-5x-to-60)
78

9+
## Upgrading from 7.x to 8.0
10+
11+
### 8.0 High Impact Changes
12+
13+
- [Updating Dependencies](#80-updating-dependencies)
14+
- [EasyPostClient](#80-easypostclient)
15+
- [Improved Error Handling](#80-improved-error-handling)
16+
17+
### 8.0 Medium Impact Changes
18+
19+
- [Corrected Naming Conventions](#80-corrected-naming-conventions)
20+
21+
### 8.0 Low Impact Changes
22+
23+
- [Beta Namespace Changed](#80-beta-namespace-changed)
24+
- [Changed Function Parameter Order and Return Types](#80-changed-function-parameter-order-and-return-types)
25+
26+
## 8.0 Updating Dependencies
27+
28+
Likelihood of Impact: High
29+
30+
**Python 3.7 Required**
31+
32+
easypost-python now requires Python 3.7 or greater.
33+
34+
**Dependencies**
35+
36+
All dependencies had minor version bumps.
37+
38+
## 8.0 EasyPostClient
39+
40+
Likelihood of Impact: High
41+
42+
This library is now thread-safe with the introduction of a new `EasyPostClient` object. Instead of defining a global API key that all requests use, you create an `EasyPostClient` object and pass your API key to it. You then call your desired functions against a "service" which coincide with EasyPost objects:
43+
44+
```python
45+
# Old method
46+
easypost.api_key = os.getenv('EASYPOST_API_KEY')
47+
shipment = easypost.Shipment.create({'data': 'here'})
48+
49+
# New method
50+
client = easypost.EasyPostClient(api_key=os.getenv('EASYPOST_API_KEY'))
51+
shipment = client.shipment.create({'data': 'here'})
52+
```
53+
54+
All instance methods are now static with the exception of `lowest_rate` as these make API calls and require the EasyPostClient (EasyPost objects do not contain an API key to make API calls with).
55+
56+
Previously used `.save()` instance methods are now static `.update()` functions where you specify first the ID of the object you are updating and second, the parameters that need updating.
57+
58+
Functions no longer accept an API key as an optional parameter. If you need per-function API key changes, create a new EasyPostClient object and call the function on the new client that uses the API key you need.
59+
60+
### 8.0 Improved Error Handling
61+
62+
Likelihood of Impact: High
63+
64+
There are ~2 dozen new error types that extend either `ApiError` or `EasyPostError`.
65+
66+
New ApiErrors (extends EasyPostError):
67+
68+
- `ApiError`
69+
- `EncodingError`
70+
- `ExternalApiError`
71+
- `ForbiddenError`
72+
- `GatewayTimeoutError`
73+
- `HttpError`
74+
- `InternalServerError`
75+
- `InvalidRequestError`
76+
- `JsonError`
77+
- `MethodNotAllowedError`
78+
- `NotFoundError`
79+
- `PaymentError`
80+
- `RateLimitError`
81+
- `RedirectError`
82+
- `ServiceUnavailableError`
83+
- `TimeoutError`
84+
- `UnauthorizedError`
85+
- `UnknownApiError`
86+
87+
New EasyPostErrors (extends builtin Exception):
88+
89+
- `EasyPostError`
90+
- `EndOfPaginationError`
91+
- `FilteringError`
92+
- `InvalidObjectError`
93+
- `InvalidParameterError`
94+
- `MissingParameterError`
95+
- `SignatureVerificationError`
96+
97+
ApiErrors will behave like the previous Error class did. They will include a `message`, `http_status`, and `http_body`. Additionally, a new `code` and `errors` keys are present and populate when available. This class extends the more generic `EasyPostError` which only contains a message, used for errors thrown directly from this library.
98+
99+
The `original_exception` property has been removed and is now returned directly in the error message if present.
100+
101+
### 8.0 Corrected Naming Conventions
102+
103+
Likelihood of Impact: Medium
104+
105+
Occurances of `referral` are now `referral_customer` and `Referral` are now `ReferralCustomer` to match the documentation and API.
106+
107+
Occurances of `smartrate` are now `smart_rate` and `Smartrate` are now `SmartRate` to match the documentation and API.
108+
109+
Occurances of `scanform` are now `scan_form` and `Scanform` are now `ScanForm` to match the documentation and API.
110+
111+
The `primary_or_secondary` parameter name for billing functions is now called `priority` to match the documentation and API.
112+
113+
## 8.0 Beta Namespace Changed
114+
115+
Likelihood of Impact: Low
116+
117+
Previously, the beta namespace was found at `easypost.beta.x` where `x` is the name of your model. Now, the beta namespace is simply prepended to the name of your service: `client.beta_x`. for instance, you can call `client.beta_referral_customer.add_payment_method()`.
118+
119+
## 8.0 Changed Function Parameter Order and Return Types
120+
121+
Likelihood of Impact: Low
122+
123+
The `update_email` function of the `referral_customer` service had the parameter order switched and name changed. Previously, you would pass the email and then the id, Now, you pass the `id` of the user first, then the email. This change matches the rest of the library where an ID always comes first.
124+
125+
Functions that previously returned `True` now do not return anything as there is no response body from the API (eg: `fund_wallet`, `delete_payment_method`, `update_email`, `create_list`)
126+
8127
## Upgrading from 6.x to 7.0
9128

129+
**NOTICE:** v7 is deprecated.
130+
10131
### 7.0 High Impact Changes
11132

12133
- [Updating Dependencies](#70-updating-dependencies)

easypost/constant.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# flake8: noqa
22
# Library version
3-
VERSION = "7.13.0"
3+
VERSION = "8.0.0"
44
VERSION_INFO = [str(number) for number in VERSION.split(".")]
55

66
# Client defaults

easypost/services/billing_service.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -9,7 +9,7 @@
99
NO_BILLING_ERROR,
1010
)
1111
from easypost.easypost_object import convert_to_easypost_object
12-
from easypost.errors import PaymentError
12+
from easypost.errors import InvalidObjectError
1313
from easypost.models import Billing
1414
from easypost.requestor import (
1515
RequestMethod,
@@ -49,7 +49,7 @@ def retrieve_payment_methods(self, **params) -> Dict[str, Any]:
4949
)
5050

5151
if response.get("id") is None:
52-
raise PaymentError(message=NO_BILLING_ERROR)
52+
raise InvalidObjectError(message=NO_BILLING_ERROR)
5353

5454
return convert_to_easypost_object(response=response)
5555

@@ -71,8 +71,8 @@ def _get_payment_method_info(self, priority: str = "primary") -> List[str]:
7171
elif payment_method_id.startswith("bank_"):
7272
endpoint = "/bank_accounts"
7373
else:
74-
raise PaymentError(message=INVALID_PAYMENT_METHOD_ERROR)
74+
raise InvalidObjectError(message=INVALID_PAYMENT_METHOD_ERROR)
7575
else:
76-
raise PaymentError(message=INVALID_PAYMENT_METHOD_ERROR)
76+
raise InvalidObjectError(message=INVALID_PAYMENT_METHOD_ERROR)
7777

7878
return [endpoint, payment_method_id]

setup.py

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333

3434
setup(
3535
name="easypost",
36-
version="7.13.0",
36+
version="8.0.0",
3737
description="EasyPost Shipping API Client Library for Python",
3838
author="EasyPost",
3939
author_email="[email protected]",

tests/test_billing.py

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -3,7 +3,7 @@
33
import pytest
44

55
import easypost
6-
from easypost.errors import PaymentError
6+
from easypost.errors import InvalidObjectError
77

88

99
@patch(
@@ -54,7 +54,7 @@ def test_billing_payment_method_delete_bank_account(mock_request, mock_payment_m
5454
@patch("easypost.services.billing_service.Requestor.request", return_value={"mock": "response"})
5555
def test_billing_payment_method_delete_invalid(mock_request, mock_payment_methods, prod_client):
5656
"""Tests we raise an error when we receive an invalid payment method"""
57-
with pytest.raises(PaymentError):
57+
with pytest.raises(InvalidObjectError):
5858
_ = prod_client.billing.delete_payment_method(priority="primary")
5959

6060

@@ -65,7 +65,7 @@ def test_billing_payment_method_delete_invalid(mock_request, mock_payment_method
6565
@patch("easypost.services.billing_service.Requestor.request", return_value={"mock": "response"})
6666
def test_billing_payment_method_delete_bad_request(mock_request, mock_payment_methods, prod_client):
6767
"""Tests we raise an error when we cannot retrieve a payment method."""
68-
with pytest.raises(PaymentError):
68+
with pytest.raises(InvalidObjectError):
6969
_ = prod_client.billing.delete_payment_method(priority="tertiary")
7070

7171

@@ -81,7 +81,7 @@ def test_billing_retrieve_payment_methods(mock_request, prod_client):
8181
@patch("easypost.services.billing_service.Requestor.request", return_value={"mock": "response"})
8282
def test_billing_retrieve_payment_methods_no_billing_setup(mock_request, prod_client):
8383
"""Tests that we throw an error when we cannot retrieve payment methods due to no billing being setup."""
84-
with pytest.raises(PaymentError) as error:
84+
with pytest.raises(InvalidObjectError) as error:
8585
_ = prod_client.billing.retrieve_payment_methods()
8686

8787
mock_request.assert_called_once()

0 commit comments

Comments
 (0)