python-bestbuy 0.2.2__tar.gz → 0.2.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/PKG-INFO +1 -1
- python_bestbuy-0.2.3/bestbuy/exceptions/__init__.py +123 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/models/__init__.py +4 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/models/commerce.py +80 -20
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/utils/errors.py +19 -3
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/pyproject.toml +1 -1
- python_bestbuy-0.2.2/bestbuy/exceptions.py +0 -59
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/.gitignore +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/LICENSE +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/README.md +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/__init__.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/clients/__init__.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/clients/base.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/clients/catalog.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/clients/commerce.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/configs/__init__.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/configs/base.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/configs/catalog.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/configs/commerce.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/loggers.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/models/catalog.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/operations/__init__.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/operations/base.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/operations/catalog.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/operations/commerce.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/operations/pagination.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/py.typed +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/query.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/typing.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/utils/__init__.py +0 -0
- {python_bestbuy-0.2.2 → python_bestbuy-0.2.3}/bestbuy/utils/encryption.py +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: python-bestbuy
|
|
3
|
-
Version: 0.2.
|
|
3
|
+
Version: 0.2.3
|
|
4
4
|
Summary: Python client library for Best Buy's Catalog and Commerce APIs
|
|
5
5
|
Project-URL: Homepage, https://github.com/bbify/python-bestbuy
|
|
6
6
|
Project-URL: Repository, https://github.com/bbify/python-bestbuy
|
|
@@ -0,0 +1,123 @@
|
|
|
1
|
+
"""Custom exceptions for the Best Buy API client."""
|
|
2
|
+
|
|
3
|
+
from __future__ import annotations
|
|
4
|
+
|
|
5
|
+
from dataclasses import dataclass
|
|
6
|
+
|
|
7
|
+
|
|
8
|
+
class BestBuyError(Exception):
|
|
9
|
+
"""Base exception for all Best Buy API errors."""
|
|
10
|
+
|
|
11
|
+
pass
|
|
12
|
+
|
|
13
|
+
|
|
14
|
+
class ConfigError(BestBuyError):
|
|
15
|
+
"""Raised when there's an error with client configuration."""
|
|
16
|
+
|
|
17
|
+
pass
|
|
18
|
+
|
|
19
|
+
|
|
20
|
+
class AuthenticationError(BestBuyError):
|
|
21
|
+
"""Raised when authentication fails."""
|
|
22
|
+
|
|
23
|
+
pass
|
|
24
|
+
|
|
25
|
+
|
|
26
|
+
class SessionRequiredError(BestBuyError):
|
|
27
|
+
"""Raised when an operation requires an active session but none exists."""
|
|
28
|
+
|
|
29
|
+
pass
|
|
30
|
+
|
|
31
|
+
|
|
32
|
+
class APIError(BestBuyError):
|
|
33
|
+
"""Raised when the API returns an error.
|
|
34
|
+
|
|
35
|
+
Used to handle errors from both Commerce and Catalog APIs.
|
|
36
|
+
|
|
37
|
+
Attributes:
|
|
38
|
+
message: Human-readable error message
|
|
39
|
+
code: Error code from the API (if available)
|
|
40
|
+
sku: SKU that caused the error (if available)
|
|
41
|
+
response_text: Raw response text (XML or JSON)
|
|
42
|
+
"""
|
|
43
|
+
|
|
44
|
+
def __init__(
|
|
45
|
+
self,
|
|
46
|
+
message: str,
|
|
47
|
+
code: str | None = None,
|
|
48
|
+
sku: str | None = None,
|
|
49
|
+
response_text: str | None = None,
|
|
50
|
+
):
|
|
51
|
+
self.message = message
|
|
52
|
+
self.code = code
|
|
53
|
+
self.sku = sku
|
|
54
|
+
self.response_text = response_text
|
|
55
|
+
|
|
56
|
+
# Build error message
|
|
57
|
+
parts = [message]
|
|
58
|
+
if code:
|
|
59
|
+
parts.append(f"Error code: {code}")
|
|
60
|
+
if sku:
|
|
61
|
+
parts.append(f"SKU: {sku}")
|
|
62
|
+
|
|
63
|
+
super().__init__(" | ".join(parts))
|
|
64
|
+
|
|
65
|
+
|
|
66
|
+
# Commerce-specific exceptions
|
|
67
|
+
|
|
68
|
+
|
|
69
|
+
@dataclass
|
|
70
|
+
class OrderErrorMessage:
|
|
71
|
+
"""A single message from a commerce order error response.
|
|
72
|
+
|
|
73
|
+
Attributes:
|
|
74
|
+
code: The error code (from the ``item-id`` XML attribute),
|
|
75
|
+
e.g. ``"INVALID_CID"``, ``"MISSINGPARTNERID"``.
|
|
76
|
+
text: The human-readable error message.
|
|
77
|
+
"""
|
|
78
|
+
|
|
79
|
+
code: str
|
|
80
|
+
text: str
|
|
81
|
+
|
|
82
|
+
|
|
83
|
+
class CommerceOrderError(APIError):
|
|
84
|
+
"""Raised when the Commerce API rejects an order (HTTP 400).
|
|
85
|
+
|
|
86
|
+
Contains structured error messages from the
|
|
87
|
+
``<order-response><messages>`` element. Multiple messages may be
|
|
88
|
+
present when several validation errors occur simultaneously.
|
|
89
|
+
|
|
90
|
+
Inherits from :class:`APIError` so existing ``except APIError``
|
|
91
|
+
catch blocks still work. Callers can also catch
|
|
92
|
+
``CommerceOrderError`` specifically for structured access to the
|
|
93
|
+
error messages list.
|
|
94
|
+
|
|
95
|
+
Attributes:
|
|
96
|
+
messages: List of structured error messages with codes.
|
|
97
|
+
"""
|
|
98
|
+
|
|
99
|
+
def __init__(
|
|
100
|
+
self,
|
|
101
|
+
messages: list[OrderErrorMessage],
|
|
102
|
+
response_text: str | None = None,
|
|
103
|
+
) -> None:
|
|
104
|
+
self.messages = messages
|
|
105
|
+
primary = (
|
|
106
|
+
messages[0]
|
|
107
|
+
if messages
|
|
108
|
+
else OrderErrorMessage(code="UNKNOWN", text="Unknown order error")
|
|
109
|
+
)
|
|
110
|
+
|
|
111
|
+
parts = [primary.text]
|
|
112
|
+
if primary.code:
|
|
113
|
+
parts.append(f"Error code: {primary.code}")
|
|
114
|
+
if len(messages) > 1:
|
|
115
|
+
parts.append(f"{len(messages)} total errors")
|
|
116
|
+
|
|
117
|
+
# Initialize APIError fields directly (skip APIError.__init__
|
|
118
|
+
# to control the str representation)
|
|
119
|
+
self.message = primary.text
|
|
120
|
+
self.code = primary.code
|
|
121
|
+
self.sku = None
|
|
122
|
+
self.response_text = response_text
|
|
123
|
+
BestBuyError.__init__(self, " | ".join(parts))
|
|
@@ -88,9 +88,11 @@ from .commerce import (
|
|
|
88
88
|
OrderList,
|
|
89
89
|
OrderQueryRequest,
|
|
90
90
|
OrderResponse,
|
|
91
|
+
OrderResponseMessage,
|
|
91
92
|
OrderSubmitGuestRequest,
|
|
92
93
|
OrderSubmitRegisteredRequest,
|
|
93
94
|
OrderSubmitResponse,
|
|
95
|
+
OrderItemStatus,
|
|
94
96
|
OrderStatus,
|
|
95
97
|
PriceQueryRequest,
|
|
96
98
|
PriceResponse,
|
|
@@ -201,9 +203,11 @@ __all__ = [
|
|
|
201
203
|
"OrderList",
|
|
202
204
|
"OrderQueryRequest",
|
|
203
205
|
"OrderResponse",
|
|
206
|
+
"OrderResponseMessage",
|
|
204
207
|
"OrderSubmitGuestRequest",
|
|
205
208
|
"OrderSubmitRegisteredRequest",
|
|
206
209
|
"OrderSubmitResponse",
|
|
210
|
+
"OrderItemStatus",
|
|
207
211
|
"OrderStatus",
|
|
208
212
|
"PriceQueryRequest",
|
|
209
213
|
"PriceResponse",
|
|
@@ -7,32 +7,75 @@ from pydantic_xml import BaseXmlModel, element, attr, wrapped
|
|
|
7
7
|
|
|
8
8
|
|
|
9
9
|
class OrderStatus(str, Enum):
|
|
10
|
+
"""Overall order status values returned by the Commerce API."""
|
|
11
|
+
|
|
12
|
+
CLOSED = "CLOSED"
|
|
13
|
+
INCOMPLETE = "INCOMPLETE"
|
|
14
|
+
PAYMENT_COLLECTED = "PAYMENT_COLLECTED"
|
|
15
|
+
RECEIVED = "RECEIVED"
|
|
16
|
+
SHIPPED = "SHIPPED"
|
|
17
|
+
SHIPPING = "SHIPPING"
|
|
18
|
+
SUBMITTED = "SUBMITTED"
|
|
19
|
+
WAITING_ACCEPTANCE = "WAITING_ACCEPTANCE"
|
|
20
|
+
|
|
21
|
+
|
|
22
|
+
class OrderItemStatus(str, Enum):
|
|
23
|
+
"""Line-item status values for individual items in an order."""
|
|
24
|
+
|
|
25
|
+
# Item is waiting to be picked up for return.
|
|
10
26
|
AWAITING_RETURN_PICKUP = "Awaiting Return Pickup"
|
|
27
|
+
# Your appointment has not been set
|
|
11
28
|
AWAITING_SCHEDULING = "Awaiting Scheduling"
|
|
29
|
+
# Item is currently backordered and cannot be fulfilled until more
|
|
30
|
+
# inventory becomes available
|
|
12
31
|
BACKORDERED = "Backordered"
|
|
32
|
+
# Your item was canceled
|
|
13
33
|
CANCELED = "Canceled"
|
|
34
|
+
# The process of order through fulfillment is completed/delivered
|
|
35
|
+
# to the end user
|
|
14
36
|
COMPLETED = "Completed"
|
|
37
|
+
# Carrier has indicated that your shipment may have been delayed
|
|
15
38
|
DELAYED = "Delayed"
|
|
39
|
+
# The process of order through fulfillment is completed/delivered
|
|
40
|
+
# to the end user
|
|
16
41
|
DELIVERED = "Delivered"
|
|
42
|
+
# Order is in progress — still going through statuses before delivery
|
|
17
43
|
IN_PROGRESS = "In Progress"
|
|
18
|
-
|
|
44
|
+
# The item has been returned
|
|
19
45
|
ITEM_RETURNED = "Item Returned"
|
|
46
|
+
# Your order has been received
|
|
20
47
|
ORDER_RECEIVED = "Order Received"
|
|
48
|
+
# The item is out for delivery
|
|
21
49
|
OUT_FOR_DELIVERY = "Out for Delivery"
|
|
50
|
+
# The item is out of stock and awaiting more inventory
|
|
22
51
|
OUT_OF_STOCK = "Out of Stock"
|
|
52
|
+
# Pending cancellation (rarely seen)
|
|
23
53
|
PENDING_CANCELLATION = "Pending Cancellation"
|
|
54
|
+
# The item was picked up (usually store pickup fulfillment)
|
|
24
55
|
PICKED_UP = "Picked Up"
|
|
56
|
+
# Item is on pre-order and not yet available for shipping
|
|
25
57
|
PRE_ORDERED = "Pre-Ordered"
|
|
58
|
+
# Getting the item ready for shipment or delivery
|
|
26
59
|
PREPARING = "Preparing"
|
|
60
|
+
# The item is ready to be picked up at the store
|
|
27
61
|
READY_TO_PICK_UP = "Ready to Pick Up"
|
|
62
|
+
# Item is pending a refund
|
|
28
63
|
REFUND_PENDING = "Refund Pending"
|
|
64
|
+
# Your appointment needs to be rescheduled
|
|
29
65
|
RESCHEDULE_REQUIRED = "Reschedule Required"
|
|
66
|
+
# The returning item is in transit to the return warehouse
|
|
30
67
|
RETURN_IN_TRANSIT = "Return In Transit"
|
|
68
|
+
# The item has been received by the return warehouse and is in review
|
|
31
69
|
RETURN_RECEIVED = "Return Received"
|
|
70
|
+
# Confirmation of a return request
|
|
32
71
|
RETURN_REQUEST_CONFIRMED = "Return Request Confirmed"
|
|
72
|
+
# Item has been returned
|
|
33
73
|
RETURNED = "Returned"
|
|
74
|
+
# Item is scheduled for fulfillment
|
|
34
75
|
SCHEDULED = "Scheduled"
|
|
76
|
+
# Item needs to be scheduled
|
|
35
77
|
SCHEDULING_NEEDED = "Scheduling Needed"
|
|
78
|
+
# Item has shipped
|
|
36
79
|
SHIPPED = "Shipped"
|
|
37
80
|
|
|
38
81
|
|
|
@@ -80,13 +123,17 @@ class AvailabilityQueryRequest(BaseXmlModel, tag="availability-query"):
|
|
|
80
123
|
|
|
81
124
|
|
|
82
125
|
class AvailabilityQueryResponse(BaseXmlModel, tag="availability-query"):
|
|
83
|
-
sku_id: str = attr(name="sku-id")
|
|
84
|
-
order_code: int = element(tag="order-code")
|
|
85
|
-
display_message: str = element(tag="display-message")
|
|
86
|
-
home_delivery_code: int = element(tag="home-delivery-code")
|
|
87
|
-
home_delivery_message: str = element(
|
|
88
|
-
|
|
89
|
-
|
|
126
|
+
sku_id: Optional[str] = attr(name="sku-id", default=None)
|
|
127
|
+
order_code: Optional[int] = element(tag="order-code", default=None)
|
|
128
|
+
display_message: Optional[str] = element(tag="display-message", default=None)
|
|
129
|
+
home_delivery_code: Optional[int] = element(tag="home-delivery-code", default=None)
|
|
130
|
+
home_delivery_message: Optional[str] = element(
|
|
131
|
+
tag="home-delivery-message", default=None
|
|
132
|
+
)
|
|
133
|
+
instore_availability: Optional[bool] = element(
|
|
134
|
+
tag="instore-availability", default=None
|
|
135
|
+
)
|
|
136
|
+
max_quantity: Optional[int] = element(tag="max-quantity", default=None)
|
|
90
137
|
available_for_shipping: Optional[bool] = element(
|
|
91
138
|
tag="available-for-shipping", default=None
|
|
92
139
|
)
|
|
@@ -125,8 +172,8 @@ class ShippingOption(BaseXmlModel, tag="option"):
|
|
|
125
172
|
|
|
126
173
|
|
|
127
174
|
class ShippingOptionsResponse(BaseXmlModel, tag="shipping-options"):
|
|
128
|
-
sku_id: str = attr(name="sku-id")
|
|
129
|
-
free_shipping: bool = attr(name="free-shipping")
|
|
175
|
+
sku_id: Optional[str] = attr(name="sku-id", default=None)
|
|
176
|
+
free_shipping: Optional[bool] = attr(name="free-shipping", default=None)
|
|
130
177
|
options: List[ShippingOption] = element(tag="option", default_factory=list)
|
|
131
178
|
|
|
132
179
|
|
|
@@ -188,13 +235,17 @@ class ProductServiceRequest(BaseXmlModel, tag="productservice-request"):
|
|
|
188
235
|
|
|
189
236
|
|
|
190
237
|
class AvailabilityQuery(BaseXmlModel, tag="availability-query"):
|
|
191
|
-
sku_id: str = attr(name="sku-id")
|
|
192
|
-
order_code: int = element(tag="order-code")
|
|
193
|
-
display_message: str = element(tag="display-message")
|
|
194
|
-
home_delivery_code: int = element(tag="home-delivery-code")
|
|
195
|
-
home_delivery_message: str = element(
|
|
196
|
-
|
|
197
|
-
|
|
238
|
+
sku_id: Optional[str] = attr(name="sku-id", default=None)
|
|
239
|
+
order_code: Optional[int] = element(tag="order-code", default=None)
|
|
240
|
+
display_message: Optional[str] = element(tag="display-message", default=None)
|
|
241
|
+
home_delivery_code: Optional[int] = element(tag="home-delivery-code", default=None)
|
|
242
|
+
home_delivery_message: Optional[str] = element(
|
|
243
|
+
tag="home-delivery-message", default=None
|
|
244
|
+
)
|
|
245
|
+
instore_availability: Optional[bool] = element(
|
|
246
|
+
tag="instore-availability", default=None
|
|
247
|
+
)
|
|
248
|
+
max_quantity: Optional[int] = element(tag="max-quantity", default=None)
|
|
198
249
|
|
|
199
250
|
|
|
200
251
|
class ProductServiceResponse(BaseXmlModel, tag="productservice-response"):
|
|
@@ -239,7 +290,7 @@ class OrderItem(BaseXmlModel, tag="item"):
|
|
|
239
290
|
cancellable: Optional[bool] = attr(name="cancellable", default=None)
|
|
240
291
|
parent_item: Optional[str] = attr(name="parent-item", default=None)
|
|
241
292
|
type: Optional[str] = attr(name="type", default=None)
|
|
242
|
-
line_status: Optional[
|
|
293
|
+
line_status: Optional[OrderItemStatus] = attr(name="line-status", default=None)
|
|
243
294
|
line_status_message: Optional[str] = attr(name="line-status-message", default=None)
|
|
244
295
|
expected_delivery_date: Optional[str] = attr(
|
|
245
296
|
name="expected-delivery-date", default=None
|
|
@@ -557,7 +608,7 @@ class OrderResponse(BaseXmlModel, tag="order", search_mode="unordered"):
|
|
|
557
608
|
id: Optional[str] = attr(name="id", default=None)
|
|
558
609
|
reviewable: Optional[bool] = attr(name="reviewable", default=None)
|
|
559
610
|
partner_id: Optional[str] = attr(name="partner-id", default=None)
|
|
560
|
-
status: Optional[
|
|
611
|
+
status: Optional[str] = attr(name="status", default=None)
|
|
561
612
|
order_date: Optional[date] = attr(name="order-date", default=None)
|
|
562
613
|
total: Optional[Decimal] = attr(name="total", default=None)
|
|
563
614
|
given_id: Optional[str] = attr(name="given-id", default=None)
|
|
@@ -576,6 +627,13 @@ class IdMapEntry(BaseXmlModel, tag="entry"):
|
|
|
576
627
|
value: str = element(tag="value")
|
|
577
628
|
|
|
578
629
|
|
|
630
|
+
class OrderResponseMessage(BaseXmlModel, tag="message"):
|
|
631
|
+
"""A message from an order response (warning/info on success, error on 400)."""
|
|
632
|
+
|
|
633
|
+
item_id: Optional[str] = attr(name="item-id", default=None)
|
|
634
|
+
text: Optional[str] = None
|
|
635
|
+
|
|
636
|
+
|
|
579
637
|
class OrderSubmitResponse(BaseXmlModel, tag="order-response"):
|
|
580
638
|
version: str = attr(name="version")
|
|
581
639
|
status: str = attr(name="status")
|
|
@@ -583,7 +641,9 @@ class OrderSubmitResponse(BaseXmlModel, tag="order-response"):
|
|
|
583
641
|
id_map: Optional[List[IdMapEntry]] = wrapped(
|
|
584
642
|
"id-map", element(tag="entry", default_factory=list)
|
|
585
643
|
)
|
|
586
|
-
messages:
|
|
644
|
+
messages: List[OrderResponseMessage] = wrapped(
|
|
645
|
+
"messages", element(tag="message", default_factory=list)
|
|
646
|
+
)
|
|
587
647
|
|
|
588
648
|
|
|
589
649
|
class PublicKeyEncryptionResponse(BaseXmlModel, tag="publicKeyEncryption"):
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import json
|
|
2
2
|
from xml.etree import ElementTree as ET
|
|
3
3
|
|
|
4
|
-
from ..exceptions import APIError
|
|
4
|
+
from ..exceptions import APIError, CommerceOrderError, OrderErrorMessage
|
|
5
5
|
from ..models import ApiError, ApiErrors, SimpleError
|
|
6
6
|
|
|
7
7
|
|
|
@@ -80,19 +80,35 @@ def check_for_xml_errors(response_text: str | None) -> None:
|
|
|
80
80
|
except Exception:
|
|
81
81
|
pass
|
|
82
82
|
|
|
83
|
+
# Check for order-response messages format:
|
|
84
|
+
# <order-response><messages><message item-id="CODE">text</message>
|
|
85
|
+
elif root.tag == "order-response":
|
|
86
|
+
messages_elem = root.find("messages")
|
|
87
|
+
if messages_elem is not None:
|
|
88
|
+
order_messages = []
|
|
89
|
+
for msg_elem in messages_elem.findall("message"):
|
|
90
|
+
code = msg_elem.get("item-id", "UNKNOWN")
|
|
91
|
+
text = msg_elem.text or ""
|
|
92
|
+
order_messages.append(OrderErrorMessage(code=code, text=text))
|
|
93
|
+
if order_messages:
|
|
94
|
+
raise CommerceOrderError(
|
|
95
|
+
messages=order_messages,
|
|
96
|
+
response_text=response_text,
|
|
97
|
+
)
|
|
98
|
+
|
|
83
99
|
# Check for errors embedded in other response types
|
|
84
100
|
else:
|
|
85
101
|
# Look for <error> child elements
|
|
86
102
|
error_elem = root.find(".//error")
|
|
87
103
|
if error_elem is not None:
|
|
88
|
-
|
|
104
|
+
error_code = error_elem.get("code")
|
|
89
105
|
message_elem = error_elem.find("message")
|
|
90
106
|
if message_elem is not None:
|
|
91
107
|
message = message_elem.text or "Unknown error"
|
|
92
108
|
sku = message_elem.get("sku")
|
|
93
109
|
raise APIError(
|
|
94
110
|
message=message,
|
|
95
|
-
code=
|
|
111
|
+
code=error_code,
|
|
96
112
|
sku=sku,
|
|
97
113
|
response_text=response_text,
|
|
98
114
|
)
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
"""Custom exceptions for the Best Buy API client."""
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
class BestBuyError(Exception):
|
|
5
|
-
"""Base exception for all Best Buy API errors."""
|
|
6
|
-
|
|
7
|
-
pass
|
|
8
|
-
|
|
9
|
-
|
|
10
|
-
class ConfigError(BestBuyError):
|
|
11
|
-
"""Raised when there's an error with client configuration."""
|
|
12
|
-
|
|
13
|
-
pass
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
class AuthenticationError(BestBuyError):
|
|
17
|
-
"""Raised when authentication fails."""
|
|
18
|
-
|
|
19
|
-
pass
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
class SessionRequiredError(BestBuyError):
|
|
23
|
-
"""Raised when an operation requires an active session but none exists."""
|
|
24
|
-
|
|
25
|
-
pass
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
class APIError(BestBuyError):
|
|
29
|
-
"""Raised when the API returns an error.
|
|
30
|
-
|
|
31
|
-
Used to handle errors from both Commerce and Catalog APIs.
|
|
32
|
-
|
|
33
|
-
Attributes:
|
|
34
|
-
message: Human-readable error message
|
|
35
|
-
code: Error code from the API (if available)
|
|
36
|
-
sku: SKU that caused the error (if available)
|
|
37
|
-
response_text: Raw response text (XML or JSON)
|
|
38
|
-
"""
|
|
39
|
-
|
|
40
|
-
def __init__(
|
|
41
|
-
self,
|
|
42
|
-
message: str,
|
|
43
|
-
code: str | None = None,
|
|
44
|
-
sku: str | None = None,
|
|
45
|
-
response_text: str | None = None,
|
|
46
|
-
):
|
|
47
|
-
self.message = message
|
|
48
|
-
self.code = code
|
|
49
|
-
self.sku = sku
|
|
50
|
-
self.response_text = response_text
|
|
51
|
-
|
|
52
|
-
# Build error message
|
|
53
|
-
parts = [message]
|
|
54
|
-
if code:
|
|
55
|
-
parts.append(f"Error code: {code}")
|
|
56
|
-
if sku:
|
|
57
|
-
parts.append(f"SKU: {sku}")
|
|
58
|
-
|
|
59
|
-
super().__init__(" | ".join(parts))
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|