python-bestbuy 0.2.1__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.
Files changed (31) hide show
  1. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/PKG-INFO +1 -1
  2. python_bestbuy-0.2.3/bestbuy/exceptions/__init__.py +123 -0
  3. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/models/__init__.py +4 -0
  4. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/models/commerce.py +97 -21
  5. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/utils/errors.py +19 -3
  6. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/pyproject.toml +1 -1
  7. python_bestbuy-0.2.1/bestbuy/exceptions.py +0 -59
  8. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/.gitignore +0 -0
  9. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/LICENSE +0 -0
  10. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/README.md +0 -0
  11. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/__init__.py +0 -0
  12. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/clients/__init__.py +0 -0
  13. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/clients/base.py +0 -0
  14. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/clients/catalog.py +0 -0
  15. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/clients/commerce.py +0 -0
  16. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/configs/__init__.py +0 -0
  17. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/configs/base.py +0 -0
  18. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/configs/catalog.py +0 -0
  19. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/configs/commerce.py +0 -0
  20. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/loggers.py +0 -0
  21. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/models/catalog.py +0 -0
  22. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/operations/__init__.py +0 -0
  23. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/operations/base.py +0 -0
  24. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/operations/catalog.py +0 -0
  25. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/operations/commerce.py +0 -0
  26. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/operations/pagination.py +0 -0
  27. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/py.typed +0 -0
  28. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/query.py +0 -0
  29. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/typing.py +0 -0
  30. {python_bestbuy-0.2.1 → python_bestbuy-0.2.3}/bestbuy/utils/__init__.py +0 -0
  31. {python_bestbuy-0.2.1 → 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.1
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
- INCOMPLETE = "Incomplete"
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(tag="home-delivery-message")
88
- instore_availability: bool = element(tag="instore-availability")
89
- max_quantity: int = element(tag="max-quantity")
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(tag="home-delivery-message")
196
- instore_availability: bool = element(tag="instore-availability")
197
- max_quantity: int = element(tag="max-quantity")
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"):
@@ -236,6 +287,14 @@ class OrderItem(BaseXmlModel, tag="item"):
236
287
  link: Optional[Link] = element(tag="link", default=None)
237
288
  sku: Optional[str] = attr(name="sku", default=None)
238
289
  backordered: Optional[bool] = attr(name="backordered", default=None)
290
+ cancellable: Optional[bool] = attr(name="cancellable", default=None)
291
+ parent_item: Optional[str] = attr(name="parent-item", default=None)
292
+ type: Optional[str] = attr(name="type", default=None)
293
+ line_status: Optional[OrderItemStatus] = attr(name="line-status", default=None)
294
+ line_status_message: Optional[str] = attr(name="line-status-message", default=None)
295
+ expected_delivery_date: Optional[str] = attr(
296
+ name="expected-delivery-date", default=None
297
+ )
239
298
  description: Optional[str] = element(tag="description", default=None)
240
299
  unit_price: Optional[UnitPrice] = element(tag="unit-price", default=None)
241
300
  cost: Optional[Cost] = element(tag="cost", default=None)
@@ -274,13 +333,17 @@ class Shipping(BaseXmlModel, tag="shipping"):
274
333
 
275
334
  class AddressFulfillment(BaseXmlModel, tag="address-fulfillment"):
276
335
  list: Optional[str] = attr(name="list", default=None)
277
- item_id: str = attr(name="item-id")
336
+ item_id: Optional[str] = attr(name="item-id", default=None)
278
337
  shipping: Optional[Shipping] = element(tag="shipping", default=None)
279
338
  address: Optional[OrderAddress] = element(tag="address", default=None)
280
339
  id: Optional[str] = attr(name="id", default=None)
281
340
  estimated_shipping_date: Optional[date] = attr(
282
341
  name="estimated-shipping-date", default=None
283
342
  )
343
+ shipping_option: Optional[str] = attr(name="shipping-option", default=None)
344
+ shipment_date: Optional[str] = attr(name="shipment-date", default=None)
345
+ shipment_carrier: Optional[str] = attr(name="shipment-carrier", default=None)
346
+ tracking_number: Optional[str] = attr(name="tracking-number", default=None)
284
347
 
285
348
 
286
349
  class FriendsFamilyDetails(BaseXmlModel, tag="friends-family-details"):
@@ -310,6 +373,7 @@ class HomeDeliveryFulfillment(BaseXmlModel, tag="homedelivery-fulfillment"):
310
373
 
311
374
 
312
375
  class Fulfillment(BaseXmlModel, tag="fulfillment"):
376
+ status: Optional[str] = attr(name="status", default=None)
313
377
  address_fulfillment: Optional[AddressFulfillment] = element(
314
378
  tag="address-fulfillment", default=None
315
379
  )
@@ -336,6 +400,7 @@ class CCTender(BaseXmlModel, tag="cc-tender"):
336
400
 
337
401
  cid: Optional[str] = attr(name="cid", default=None)
338
402
  last_four: Optional[str] = attr(name="last-four", default=None)
403
+ list: Optional[str] = attr(name="list", default=None)
339
404
  name: Optional[str] = attr(name="name", default=None)
340
405
  id: Optional[str] = attr(name="id", default=None)
341
406
  exp_date: Optional[str] = attr(name="exp-date", default=None)
@@ -516,6 +581,7 @@ class OrderSubmitRegisteredRequest(BaseXmlModel, tag="order"):
516
581
 
517
582
  id: str = attr(name="id")
518
583
  partner_id: Optional[str] = attr(name="partner-id", default=None)
584
+ tec_code: Optional[str] = attr(name="tec-code", default=None)
519
585
  reviewable: bool = attr(name="reviewable", default=False)
520
586
  order_list: OrderList = element(tag="list")
521
587
  fulfillment: Fulfillment = element(tag="fulfillment")
@@ -531,17 +597,18 @@ class OrderSubmitGuestRequest(BaseXmlModel, tag="order"):
531
597
 
532
598
  id: str = attr(name="id")
533
599
  partner_id: Optional[str] = attr(name="partner-id", default=None)
600
+ tec_code: Optional[str] = attr(name="tec-code", default=None)
534
601
  reviewable: bool = attr(name="reviewable", default=False)
535
602
  order_list: OrderList = element(tag="list")
536
603
  fulfillment: Fulfillment = element(tag="fulfillment")
537
604
  tender: GuestTender = element(tag="tender")
538
605
 
539
606
 
540
- class OrderResponse(BaseXmlModel, tag="order"):
607
+ class OrderResponse(BaseXmlModel, tag="order", search_mode="unordered"):
541
608
  id: Optional[str] = attr(name="id", default=None)
542
609
  reviewable: Optional[bool] = attr(name="reviewable", default=None)
543
610
  partner_id: Optional[str] = attr(name="partner-id", default=None)
544
- status: Optional[OrderStatus] = attr(name="status", default=None)
611
+ status: Optional[str] = attr(name="status", default=None)
545
612
  order_date: Optional[date] = attr(name="order-date", default=None)
546
613
  total: Optional[Decimal] = attr(name="total", default=None)
547
614
  given_id: Optional[str] = attr(name="given-id", default=None)
@@ -560,6 +627,13 @@ class IdMapEntry(BaseXmlModel, tag="entry"):
560
627
  value: str = element(tag="value")
561
628
 
562
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
+
563
637
  class OrderSubmitResponse(BaseXmlModel, tag="order-response"):
564
638
  version: str = attr(name="version")
565
639
  status: str = attr(name="status")
@@ -567,7 +641,9 @@ class OrderSubmitResponse(BaseXmlModel, tag="order-response"):
567
641
  id_map: Optional[List[IdMapEntry]] = wrapped(
568
642
  "id-map", element(tag="entry", default_factory=list)
569
643
  )
570
- messages: Optional[str] = element(tag="messages", default=None)
644
+ messages: List[OrderResponseMessage] = wrapped(
645
+ "messages", element(tag="message", default_factory=list)
646
+ )
571
647
 
572
648
 
573
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
- code = error_elem.get("code")
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=code,
111
+ code=error_code,
96
112
  sku=sku,
97
113
  response_text=response_text,
98
114
  )
@@ -4,7 +4,7 @@ build-backend = "hatchling.build"
4
4
 
5
5
  [project]
6
6
  name = "python-bestbuy"
7
- version = "0.2.1"
7
+ version = "0.2.3"
8
8
  description = "Python client library for Best Buy's Catalog and Commerce APIs"
9
9
  readme = "README.md"
10
10
  license = "MIT"
@@ -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