python-bestbuy 0.1.0__py3-none-any.whl

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.
@@ -0,0 +1,948 @@
1
+ from datetime import date, datetime
2
+ from typing import List, Optional, Union
3
+
4
+ from pydantic import BaseModel, ConfigDict, Field
5
+
6
+
7
+ # Category Models
8
+
9
+
10
+ class CategoryPathItem(BaseModel):
11
+ """A single item in a category's path hierarchy."""
12
+
13
+ id: str
14
+ name: str
15
+
16
+
17
+ class SubCategory(BaseModel):
18
+ """A subcategory reference within a category."""
19
+
20
+ id: str
21
+ name: str
22
+
23
+
24
+ class Category(BaseModel):
25
+ """A Best Buy product category."""
26
+
27
+ model_config = ConfigDict(populate_by_name=True)
28
+
29
+ id: str
30
+ name: str
31
+ active: bool
32
+ url: str
33
+ path: List[CategoryPathItem]
34
+ sub_categories: List[SubCategory] = Field(alias="subCategories")
35
+
36
+
37
+ class CategoriesResponse(BaseModel):
38
+ """Response containing a list of categories with pagination metadata."""
39
+
40
+ model_config = ConfigDict(populate_by_name=True)
41
+
42
+ # Pagination metadata
43
+ from_: int = Field(alias="from")
44
+ to: int
45
+ current_page: int = Field(alias="currentPage")
46
+ total: int
47
+ total_pages: int = Field(alias="totalPages")
48
+ query_time: str = Field(alias="queryTime")
49
+ total_time: str = Field(alias="totalTime")
50
+ canonical_url: str = Field(alias="canonicalUrl")
51
+ partial: bool = False
52
+
53
+ # Categories
54
+ categories: List[Category]
55
+
56
+
57
+ # Product Models
58
+
59
+
60
+ class ProductImage(BaseModel):
61
+ """A product image with metadata."""
62
+
63
+ model_config = ConfigDict(populate_by_name=True)
64
+
65
+ rel: str
66
+ unit_of_measure: str = Field(alias="unitOfMeasure")
67
+ width: Optional[str] = None
68
+ height: Optional[str] = None
69
+ href: str
70
+ primary: bool
71
+
72
+
73
+ class ProductDetail(BaseModel):
74
+ """A product detail/specification."""
75
+
76
+ name: str
77
+ value: str
78
+ values: List[str]
79
+
80
+
81
+ class ProductFeature(BaseModel):
82
+ """A product feature description."""
83
+
84
+ feature: str
85
+
86
+
87
+ class IncludedItem(BaseModel):
88
+ """An item included with the product."""
89
+
90
+ model_config = ConfigDict(populate_by_name=True)
91
+
92
+ included_item: str = Field(alias="includedItem")
93
+
94
+
95
+ class ProductVariation(BaseModel):
96
+ """A variation of a product (e.g., different color)."""
97
+
98
+ name: str
99
+ value: str
100
+
101
+
102
+ class ProductVariant(BaseModel):
103
+ """A product variant with its variations."""
104
+
105
+ sku: str
106
+ variations: List[ProductVariation] = []
107
+
108
+
109
+ class RequiredPart(BaseModel):
110
+ """A required part for the product."""
111
+
112
+ sku: str
113
+
114
+
115
+ class BundledProduct(BaseModel):
116
+ """A product this item is bundled in."""
117
+
118
+ sku: Union[int, str]
119
+
120
+
121
+ class AccessorySku(BaseModel):
122
+ """An accessory SKU for a product."""
123
+
124
+ sku: int
125
+
126
+
127
+ class MemberSku(BaseModel):
128
+ """A member SKU within a bundle."""
129
+
130
+ sku: int
131
+
132
+
133
+ class ProductList(BaseModel):
134
+ """A curated list that includes this product."""
135
+
136
+ model_config = ConfigDict(populate_by_name=True)
137
+
138
+ list_id: str = Field(alias="listId")
139
+ start_date: Optional[date] = Field(default=None, alias="startDate")
140
+ end_date: Optional[date] = Field(default=None, alias="endDate")
141
+
142
+
143
+ class ShippingInfo(BaseModel):
144
+ """Shipping cost information."""
145
+
146
+ model_config = ConfigDict(populate_by_name=True)
147
+
148
+ ground: Union[float, int, str] = ""
149
+ second_day: Union[float, int, str] = Field(default="", alias="secondDay")
150
+ next_day: Union[float, int, str] = Field(default="", alias="nextDay")
151
+ vendor_delivery: str = Field(default="", alias="vendorDelivery")
152
+
153
+
154
+ class ShippingLevelOfService(BaseModel):
155
+ """A shipping service level option."""
156
+
157
+ model_config = ConfigDict(populate_by_name=True)
158
+
159
+ service_level_id: int = Field(alias="serviceLevelId")
160
+ service_level_name: str = Field(alias="serviceLevelName")
161
+ unit_shipping_price: Union[float, int] = Field(alias="unitShippingPrice")
162
+
163
+
164
+ class ContractPrice(BaseModel):
165
+ """Price information for a contract."""
166
+
167
+ model_config = ConfigDict(populate_by_name=True)
168
+
169
+ current: Union[float, int]
170
+ regular: Union[float, int]
171
+ tax_basis: Union[float, int] = Field(alias="taxBasis")
172
+ bby_down_payment: int = Field(default=0, alias="bbyDownPayment")
173
+ bill_credit_amt: int = Field(default=0, alias="billCreditAmt")
174
+ down_payment_amount: int = Field(default=0, alias="downPaymentAmount")
175
+ number_of_payments: int = Field(default=0, alias="numberOfPayments")
176
+
177
+
178
+ class ContractTerm(BaseModel):
179
+ """Contract term duration."""
180
+
181
+ duration: int
182
+ units: str
183
+
184
+
185
+ class Contract(BaseModel):
186
+ """A contract option for the product."""
187
+
188
+ model_config = ConfigDict(populate_by_name=True)
189
+
190
+ id: str
191
+ type: str
192
+ purchase_type: str = Field(alias="purchaseType")
193
+ description: str
194
+ default_contract: bool = Field(alias="defaultContract")
195
+ price_note: Optional[str] = Field(default=None, alias="priceNote")
196
+ prices: List[ContractPrice] = []
197
+ term: List[ContractTerm] = []
198
+
199
+
200
+ class GiftSku(BaseModel):
201
+ """A gift SKU included with an offer."""
202
+
203
+ sku: int
204
+ quantity: int
205
+
206
+
207
+ class Offer(BaseModel):
208
+ """A special offer for the product."""
209
+
210
+ model_config = ConfigDict(populate_by_name=True)
211
+
212
+ id: Optional[str] = None
213
+ type: str
214
+ heading: Optional[str] = None
215
+ text: Optional[str] = None
216
+ url: Optional[str] = None
217
+ image_url: Optional[str] = Field(default=None, alias="imageUrl")
218
+ offer_name: Optional[str] = Field(default=None, alias="offerName")
219
+ start_date: Optional[date] = Field(default=None, alias="startDate")
220
+ end_date: Optional[date] = Field(default=None, alias="endDate")
221
+ content_notes: Optional[str] = Field(default=None, alias="contentNotes")
222
+ gift_sku: List[GiftSku] = Field(default=[], alias="giftSku")
223
+
224
+
225
+ class PlaybackFormat(BaseModel):
226
+ """A supported playback format."""
227
+
228
+ format: str
229
+
230
+
231
+ class LanguageOption(BaseModel):
232
+ """A supported language option."""
233
+
234
+ language: str
235
+
236
+
237
+ class Product(BaseModel):
238
+ """A Best Buy product."""
239
+
240
+ model_config = ConfigDict(populate_by_name=True)
241
+
242
+ # Core identifiers
243
+ sku: int
244
+ product_id: Optional[str] = Field(default=None, alias="productId")
245
+ upc: str
246
+ name: str
247
+ model_number: str = Field(alias="modelNumber")
248
+ manufacturer: Optional[str] = None
249
+
250
+ # Classification
251
+ type: str
252
+ product_template: str = Field(alias="productTemplate")
253
+ department: str
254
+ department_id: int = Field(alias="departmentId")
255
+ class_: str = Field(alias="class")
256
+ class_id: int = Field(alias="classId")
257
+ subclass: str
258
+ subclass_id: int = Field(alias="subclassId")
259
+
260
+ # Categories
261
+ category_path: List[CategoryPathItem] = Field(alias="categoryPath")
262
+ alternate_categories: List[CategoryPathItem] = Field(
263
+ default=[], alias="alternateCategories"
264
+ )
265
+
266
+ # Pricing
267
+ regular_price: Union[float, int] = Field(alias="regularPrice")
268
+ sale_price: Union[float, int] = Field(alias="salePrice")
269
+ on_sale: bool = Field(alias="onSale")
270
+ clearance: bool
271
+ dollar_savings: Union[float, int] = Field(alias="dollarSavings")
272
+ percent_savings: str = Field(alias="percentSavings")
273
+ plan_price: Optional[float] = Field(default=None, alias="planPrice")
274
+ price_restriction: Optional[str] = Field(default=None, alias="priceRestriction")
275
+ price_update_date: datetime = Field(alias="priceUpdateDate")
276
+
277
+ # Availability
278
+ active: bool
279
+ new: bool
280
+ orderable: str
281
+ start_date: date = Field(alias="startDate")
282
+ active_update_date: datetime = Field(alias="activeUpdateDate")
283
+ in_store_availability: bool = Field(alias="inStoreAvailability")
284
+ in_store_availability_text: Optional[str] = Field(
285
+ default=None, alias="inStoreAvailabilityText"
286
+ )
287
+ in_store_availability_text_html: Optional[str] = Field(
288
+ default=None, alias="inStoreAvailabilityTextHtml"
289
+ )
290
+ in_store_availability_update_date: datetime = Field(
291
+ alias="inStoreAvailabilityUpdateDate"
292
+ )
293
+ online_availability: bool = Field(alias="onlineAvailability")
294
+ online_availability_text: Optional[str] = Field(
295
+ default=None, alias="onlineAvailabilityText"
296
+ )
297
+ online_availability_text_html: Optional[str] = Field(
298
+ default=None, alias="onlineAvailabilityTextHtml"
299
+ )
300
+ online_availability_update_date: datetime = Field(
301
+ alias="onlineAvailabilityUpdateDate"
302
+ )
303
+ release_date: Optional[date] = Field(default=None, alias="releaseDate")
304
+ item_update_date: datetime = Field(alias="itemUpdateDate")
305
+ special_order: bool = Field(alias="specialOrder")
306
+
307
+ # Fulfillment
308
+ in_store_pickup: bool = Field(alias="inStorePickup")
309
+ friends_and_family_pickup: bool = Field(alias="friendsAndFamilyPickup")
310
+ home_delivery: bool = Field(alias="homeDelivery")
311
+ free_shipping: Optional[bool] = Field(default=None, alias="freeShipping")
312
+ free_shipping_eligible: bool = Field(alias="freeShippingEligible")
313
+ shipping_cost: Union[float, int, str] = Field(default="", alias="shippingCost")
314
+ shipping: List[ShippingInfo] = []
315
+ shipping_levels_of_service: List[ShippingLevelOfService] = Field(
316
+ default=[], alias="shippingLevelsOfService"
317
+ )
318
+ shipping_weight: Union[float, int] = Field(alias="shippingWeight")
319
+ shipping_restrictions: Optional[str] = Field(
320
+ default=None, alias="shippingRestrictions"
321
+ )
322
+ quantity_limit: Optional[int] = Field(default=None, alias="quantityLimit")
323
+ fulfilled_by: Optional[str] = Field(default=None, alias="fulfilledBy")
324
+ haulaway_available: Optional[bool] = Field(default=None, alias="haulawayAvailable")
325
+
326
+ # Descriptions
327
+ short_description: Optional[str] = Field(default=None, alias="shortDescription")
328
+ short_description_html: Optional[str] = Field(
329
+ default=None, alias="shortDescriptionHtml"
330
+ )
331
+ long_description: str = Field(alias="longDescription")
332
+ long_description_html: str = Field(alias="longDescriptionHtml")
333
+ description: Optional[str] = None
334
+
335
+ # URLs
336
+ url: str
337
+ mobile_url: str = Field(alias="mobileUrl")
338
+ add_to_cart_url: str = Field(alias="addToCartUrl")
339
+ spin360_url: Optional[str] = Field(default=None, alias="spin360Url")
340
+ affiliate_url: Optional[str] = Field(default=None, alias="affiliateUrl")
341
+ affiliate_add_to_cart_url: Optional[str] = Field(
342
+ default=None, alias="affiliateAddToCartUrl"
343
+ )
344
+ link_share_affiliate_url: str = Field(default="", alias="linkShareAffiliateUrl")
345
+ link_share_affiliate_add_to_cart_url: str = Field(
346
+ default="", alias="linkShareAffiliateAddToCartUrl"
347
+ )
348
+
349
+ # Images
350
+ image: Optional[str] = None
351
+ images: List[ProductImage] = []
352
+ large_front_image: Optional[str] = Field(default=None, alias="largeFrontImage")
353
+ medium_image: Optional[str] = Field(default=None, alias="mediumImage")
354
+ thumbnail_image: Optional[str] = Field(default=None, alias="thumbnailImage")
355
+ large_image: Optional[str] = Field(default=None, alias="largeImage")
356
+ alternate_views_image: Optional[str] = Field(
357
+ default=None, alias="alternateViewsImage"
358
+ )
359
+ angle_image: Optional[str] = Field(default=None, alias="angleImage")
360
+ back_view_image: Optional[str] = Field(default=None, alias="backViewImage")
361
+ energy_guide_image: Optional[str] = Field(default=None, alias="energyGuideImage")
362
+ left_view_image: Optional[str] = Field(default=None, alias="leftViewImage")
363
+ accessories_image: Optional[str] = Field(default=None, alias="accessoriesImage")
364
+ remote_control_image: Optional[str] = Field(
365
+ default=None, alias="remoteControlImage"
366
+ )
367
+ right_view_image: Optional[str] = Field(default=None, alias="rightViewImage")
368
+ top_view_image: Optional[str] = Field(default=None, alias="topViewImage")
369
+
370
+ # Reviews
371
+ customer_review_count: Optional[int] = Field(
372
+ default=None, alias="customerReviewCount"
373
+ )
374
+ customer_review_average: Optional[Union[float, int]] = Field(
375
+ default=None, alias="customerReviewAverage"
376
+ )
377
+ customer_top_rated: Optional[bool] = Field(default=None, alias="customerTopRated")
378
+
379
+ # Product details
380
+ details: List[ProductDetail] = []
381
+ features: List[ProductFeature] = []
382
+ included_item_list: List[IncludedItem] = Field(default=[], alias="includedItemList")
383
+
384
+ # Variations and related products
385
+ product_variations: List[ProductVariant] = Field(
386
+ default=[], alias="productVariations"
387
+ )
388
+ required_parts: List[RequiredPart] = Field(default=[], alias="requiredParts")
389
+ bundled_in: List[BundledProduct] = Field(default=[], alias="bundledIn")
390
+ accessories: List[AccessorySku] = []
391
+ related_products: List[str] = Field(default=[], alias="relatedProducts")
392
+ frequently_purchased_with: List[str] = Field(
393
+ default=[], alias="frequentlyPurchasedWith"
394
+ )
395
+ cross_sell: List[str] = Field(default=[], alias="crossSell")
396
+ product_families: List[str] = Field(default=[], alias="productFamilies")
397
+ members: List[MemberSku] = []
398
+
399
+ # Contracts and offers
400
+ contracts: List[Contract] = []
401
+ offers: List[Offer] = []
402
+ price_with_plan: List[str] = Field(default=[], alias="priceWithPlan")
403
+
404
+ # Protection plans
405
+ protection_plan_term: str = Field(default="", alias="protectionPlanTerm")
406
+ protection_plan_type: Optional[str] = Field(
407
+ default=None, alias="protectionPlanType"
408
+ )
409
+ protection_plan_low_price: str = Field(default="", alias="protectionPlanLowPrice")
410
+ protection_plan_high_price: str = Field(default="", alias="protectionPlanHighPrice")
411
+ protection_plans: List[str] = Field(default=[], alias="protectionPlans")
412
+ protection_plan_details: List[str] = Field(
413
+ default=[], alias="protectionPlanDetails"
414
+ )
415
+ buyback_plans: List[str] = Field(default=[], alias="buybackPlans")
416
+ tech_support_plans: List[str] = Field(default=[], alias="techSupportPlans")
417
+
418
+ # Physical attributes
419
+ color: Optional[str] = None
420
+ condition: str
421
+ weight: Optional[str] = None
422
+ height: Optional[str] = None
423
+ width: Optional[str] = None
424
+ depth: Optional[str] = None
425
+
426
+ # Warranty
427
+ warranty_labor: Optional[str] = Field(default=None, alias="warrantyLabor")
428
+ warranty_parts: Optional[str] = Field(default=None, alias="warrantyParts")
429
+
430
+ # Digital/Preowned
431
+ digital: bool
432
+ preowned: bool
433
+
434
+ # Sales ranking
435
+ score: Optional[float] = None
436
+ sales_rank_short_term: Optional[int] = Field(
437
+ default=None, alias="salesRankShortTerm"
438
+ )
439
+ sales_rank_medium_term: Optional[int] = Field(
440
+ default=None, alias="salesRankMediumTerm"
441
+ )
442
+ sales_rank_long_term: Optional[int] = Field(default=None, alias="salesRankLongTerm")
443
+ best_selling_rank: Optional[int] = Field(default=None, alias="bestSellingRank")
444
+
445
+ # Carrier/Plan info (for phones)
446
+ carriers: List[str] = []
447
+ carrier_plans: List[str] = Field(default=[], alias="carrierPlans")
448
+ plan_features: List[str] = Field(default=[], alias="planFeatures")
449
+ devices: List[str] = []
450
+ technology_code: Optional[str] = Field(default=None, alias="technologyCode")
451
+ carrier_model_number: Optional[str] = Field(
452
+ default=None, alias="carrierModelNumber"
453
+ )
454
+ early_termination_fees: List[str] = Field(default=[], alias="earlyTerminationFees")
455
+ monthly_recurring_charge: str = Field(default="", alias="monthlyRecurringCharge")
456
+ monthly_recurring_charge_grand_total: str = Field(
457
+ default="", alias="monthlyRecurringChargeGrandTotal"
458
+ )
459
+ activation_charge: str = Field(default="", alias="activationCharge")
460
+ minute_price: str = Field(default="", alias="minutePrice")
461
+ plan_category: Optional[str] = Field(default=None, alias="planCategory")
462
+ plan_type: Optional[str] = Field(default=None, alias="planType")
463
+ family_individual_code: Optional[str] = Field(
464
+ default=None, alias="familyIndividualCode"
465
+ )
466
+ valid_from: Optional[str] = Field(default=None, alias="validFrom")
467
+ valid_until: Optional[str] = Field(default=None, alias="validUntil")
468
+ carrier_plan: Optional[str] = Field(default=None, alias="carrierPlan")
469
+
470
+ # Media info (for movies/music)
471
+ format: Optional[str] = None
472
+ album_title: str = Field(default="", alias="albumTitle")
473
+ album_label: Optional[str] = Field(default=None, alias="albumLabel")
474
+ artist_name: Optional[str] = Field(default=None, alias="artistName")
475
+ artist_id: Optional[str] = Field(default=None, alias="artistId")
476
+ original_release_date: Optional[date] = Field(
477
+ default=None, alias="originalReleaseDate"
478
+ )
479
+ parental_advisory: Optional[str] = Field(default=None, alias="parentalAdvisory")
480
+ media_count: Optional[int] = Field(default=None, alias="mediaCount")
481
+ mono_stereo: Optional[str] = Field(default=None, alias="monoStereo")
482
+ studio_live: Optional[str] = Field(default=None, alias="studioLive")
483
+ genre: Optional[str] = None
484
+ discs: List[str] = []
485
+ cast: List[str] = []
486
+ crew: List[str] = []
487
+
488
+ # Movie info
489
+ aspect_ratio: Optional[str] = Field(default=None, alias="aspectRatio")
490
+ screen_format: Optional[str] = Field(default=None, alias="screenFormat")
491
+ length_in_minutes: Optional[int] = Field(default=None, alias="lengthInMinutes")
492
+ mpaa_rating: Optional[str] = Field(default=None, alias="mpaaRating")
493
+ plot: Optional[str] = None
494
+ plot_html: Optional[str] = Field(default=None, alias="plotHtml")
495
+ studio: Optional[str] = None
496
+ theatrical_release_date: Optional[date] = Field(
497
+ default=None, alias="theatricalReleaseDate"
498
+ )
499
+
500
+ # Software/Games
501
+ software_age: Optional[str] = Field(default=None, alias="softwareAge")
502
+ software_grade: Optional[str] = Field(default=None, alias="softwareGrade")
503
+ platform: Optional[str] = None
504
+ number_of_players: Optional[int] = Field(default=None, alias="numberOfPlayers")
505
+ software_number_of_players: Optional[int] = Field(
506
+ default=None, alias="softwareNumberOfPlayers"
507
+ )
508
+ esrb_rating: Optional[str] = Field(default=None, alias="esrbRating")
509
+
510
+ # Misc
511
+ source: Optional[str] = None
512
+ search: Optional[str] = None
513
+ best_buy_item_id: str = Field(default="", alias="bestBuyItemId")
514
+ low_price_guarantee: bool = Field(alias="lowPriceGuarantee")
515
+ outlet_center: Optional[str] = Field(default=None, alias="outletCenter")
516
+ secondary_market: Optional[str] = Field(default=None, alias="secondaryMarket")
517
+ marketplace: Optional[str] = None
518
+ listing_id: Optional[str] = Field(default=None, alias="listingId")
519
+ seller_id: Optional[str] = Field(default=None, alias="sellerId")
520
+ lists: List[ProductList] = []
521
+ trade_in_value: str = Field(default="", alias="tradeInValue")
522
+ commerce_sku: int = Field(alias="commerceSku")
523
+ proposition65_warning_message: Optional[str] = Field(
524
+ default=None, alias="proposition65WarningMessage"
525
+ )
526
+ proposition65_warning_type: str = Field(
527
+ default="", alias="proposition65WarningType"
528
+ )
529
+
530
+ # Appliance-specific
531
+ capacity_cu_ft: Optional[Union[float, int]] = Field(
532
+ default=None, alias="capacityCuFt"
533
+ )
534
+ capacity_freezer_cu_ft: Optional[Union[float, int]] = Field(
535
+ default=None, alias="capacityFreezerCuFt"
536
+ )
537
+ capacity_refrigerator_cu_ft: Optional[Union[float, int]] = Field(
538
+ default=None, alias="capacityRefrigeratorCuFt"
539
+ )
540
+ counter_depth: Optional[bool] = Field(default=None, alias="counterDepth")
541
+ display_type: Optional[str] = Field(default=None, alias="displayType")
542
+ door_open_alarm: Optional[bool] = Field(default=None, alias="doorOpenAlarm")
543
+ energy_consumption_kwh_per_year: Optional[int] = Field(
544
+ default=None, alias="energyConsumptionKwhPerYear"
545
+ )
546
+ energy_star_qualified: Optional[bool] = Field(
547
+ default=None, alias="energyStarQualified"
548
+ )
549
+ estimated_yearly_operating_costs_usd: Optional[int] = Field(
550
+ default=None, alias="estimatedYearlyOperatingCostsUsd"
551
+ )
552
+ factory_installed_ice_maker: Optional[bool] = Field(
553
+ default=None, alias="factoryInstalledIceMaker"
554
+ )
555
+ gallon_door_storage: Optional[bool] = Field(default=None, alias="gallonDoorStorage")
556
+ humidity_controlled_crisper: Optional[bool] = Field(
557
+ default=None, alias="humidityControlledCrisper"
558
+ )
559
+ reversible_door_hinge: Optional[bool] = Field(
560
+ default=None, alias="reversibleDoorHinge"
561
+ )
562
+ sabbath_mode: Optional[bool] = Field(default=None, alias="sabbathMode")
563
+ shelf_construction: Optional[str] = Field(default=None, alias="shelfConstruction")
564
+ temperature_control_type: Optional[str] = Field(
565
+ default=None, alias="temperatureControlType"
566
+ )
567
+ water_filtration: Optional[bool] = Field(default=None, alias="waterFiltration")
568
+ water_filter_model_number: Optional[str] = Field(
569
+ default=None, alias="waterFilterModelNumber"
570
+ )
571
+
572
+ # Washer/Dryer specific
573
+ agitator_type: Optional[str] = Field(default=None, alias="agitatorType")
574
+ automatic_temperature_control: Optional[bool] = Field(
575
+ default=None, alias="automaticTemperatureControl"
576
+ )
577
+ bleach_dispenser: Optional[bool] = Field(default=None, alias="bleachDispenser")
578
+ child_lock: Optional[bool] = Field(default=None, alias="childLock")
579
+ control_location: Optional[str] = Field(default=None, alias="controlLocation")
580
+ control_type: Optional[str] = Field(default=None, alias="controlType")
581
+ delayed_start: Optional[bool] = Field(default=None, alias="delayedStart")
582
+ drum_and_interior_finish: Optional[str] = Field(
583
+ default=None, alias="drumAndInteriorFinish"
584
+ )
585
+ drying_rack: Optional[bool] = Field(default=None, alias="dryingRack")
586
+ end_of_cycle_signal: Optional[bool] = Field(default=None, alias="endOfCycleSignal")
587
+ fabric_dispenser: Optional[bool] = Field(default=None, alias="fabricDispenser")
588
+ interior_light: Optional[bool] = Field(default=None, alias="interiorLight")
589
+ load_access: Optional[str] = Field(default=None, alias="loadAccess")
590
+ moisture_sensor: Optional[bool] = Field(default=None, alias="moistureSensor")
591
+ pre_wash_dispenser: Optional[bool] = Field(default=None, alias="preWashDispenser")
592
+ second_rinse: Optional[bool] = Field(default=None, alias="secondRinse")
593
+ smart_capable: Optional[bool] = Field(default=None, alias="smartCapable")
594
+ stackable: Optional[bool] = None
595
+ steam: Optional[bool] = None
596
+ vibration_reduction: Optional[bool] = Field(
597
+ default=None, alias="vibrationReduction"
598
+ )
599
+
600
+ # TV/Display specific
601
+ brightness_cd_per_sq_m: Optional[str] = Field(
602
+ default=None, alias="brightnessCdPerSqM"
603
+ )
604
+ contrast_ratio: Optional[str] = Field(default=None, alias="contrastRatio")
605
+ product_aspect_ratio: Optional[str] = Field(
606
+ default=None, alias="productAspectRatio"
607
+ )
608
+ screen_refresh_rate_hz: Optional[int] = Field(
609
+ default=None, alias="screenRefreshRateHz"
610
+ )
611
+ screen_size_class_in: Optional[int] = Field(default=None, alias="screenSizeClassIn")
612
+ screen_size_in: Optional[Union[float, int]] = Field(
613
+ default=None, alias="screenSizeIn"
614
+ )
615
+ three_d_ready: Optional[bool] = Field(default=None, alias="threeDReady")
616
+ tv_type: Optional[str] = Field(default=None, alias="tvType")
617
+ v_chip: Optional[bool] = Field(default=None, alias="vChip")
618
+
619
+ # Dimensions with stand
620
+ depth_with_stand_in: Optional[Union[float, int]] = Field(
621
+ default=None, alias="depthWithStandIn"
622
+ )
623
+ depth_without_stand_in: Optional[Union[float, int]] = Field(
624
+ default=None, alias="depthWithoutStandIn"
625
+ )
626
+ height_with_stand_in: Optional[Union[float, int]] = Field(
627
+ default=None, alias="heightWithStandIn"
628
+ )
629
+ height_without_stand_in: Optional[Union[float, int]] = Field(
630
+ default=None, alias="heightWithoutStandIn"
631
+ )
632
+
633
+ # Dimensions with handles/doors
634
+ depth_including_handles_in: Optional[Union[float, int]] = Field(
635
+ default=None, alias="depthIncludingHandlesIn"
636
+ )
637
+ depth_less_door_in: Optional[Union[float, int]] = Field(
638
+ default=None, alias="depthLessDoorIn"
639
+ )
640
+ depth_with_door_open_in: Optional[Union[float, int]] = Field(
641
+ default=None, alias="depthWithDoorOpenIn"
642
+ )
643
+ depth_without_handles_in: Optional[Union[float, int]] = Field(
644
+ default=None, alias="depthWithoutHandlesIn"
645
+ )
646
+ height_to_top_of_door_hinge_in: Optional[Union[float, int]] = Field(
647
+ default=None, alias="heightToTopOfDoorHingeIn"
648
+ )
649
+ product_height_in: Optional[Union[float, int]] = Field(
650
+ default=None, alias="productHeightIn"
651
+ )
652
+
653
+ # Audio/Video connections
654
+ component_video_inputs: Optional[int] = Field(
655
+ default=None, alias="componentVideoInputs"
656
+ )
657
+ component_video_outputs: Optional[int] = Field(
658
+ default=None, alias="componentVideoOutputs"
659
+ )
660
+ composite_video_inputs: Optional[int] = Field(
661
+ default=None, alias="compositeVideoInputs"
662
+ )
663
+ composite_video_outputs: Optional[int] = Field(
664
+ default=None, alias="compositeVideoOutputs"
665
+ )
666
+ dvi_inputs: Optional[int] = Field(default=None, alias="dviInputs")
667
+ dvi_outputs: Optional[int] = Field(default=None, alias="dviOutputs")
668
+ hdmi_inputs: Optional[int] = Field(default=None, alias="hdmiInputs")
669
+ hdmi_outputs: Optional[int] = Field(default=None, alias="hdmiOutputs")
670
+ coaxial_digital_audio_outputs: Optional[bool] = Field(
671
+ default=None, alias="coaxialDigitalAudioOutputs"
672
+ )
673
+ number_of_coaxial_digital_audio_outputs: Optional[int] = Field(
674
+ default=None, alias="numberOfCoaxialDigitalAudioOutputs"
675
+ )
676
+ number_of_optical_digital_audio_outputs: Optional[int] = Field(
677
+ default=None, alias="numberOfOpticalDigitalAudioOutputs"
678
+ )
679
+ optical_digital_audio_outputs: Optional[bool] = Field(
680
+ default=None, alias="opticalDigitalAudioOutputs"
681
+ )
682
+
683
+ # Audio system specific
684
+ number_of_channels: Optional[Union[float, int]] = Field(
685
+ default=None, alias="numberOfChannels"
686
+ )
687
+ number_of_speakers: Optional[int] = Field(default=None, alias="numberOfSpeakers")
688
+ peak_power_handling: Optional[int] = Field(default=None, alias="peakPowerHandling")
689
+ total_harmonic_distortion: Optional[str] = Field(
690
+ default=None, alias="totalHarmonicDistortion"
691
+ )
692
+ total_system_power_watts: Optional[int] = Field(
693
+ default=None, alias="totalSystemPowerWatts"
694
+ )
695
+ watts_per_channel: Optional[int] = Field(default=None, alias="wattsPerChannel")
696
+ watts_per_channel_rms: Optional[int] = Field(
697
+ default=None, alias="wattsPerChannelRms"
698
+ )
699
+ wireless_subwoofer: Optional[bool] = Field(default=None, alias="wirelessSubwoofer")
700
+
701
+ # Radio specific
702
+ station_presets: Optional[int] = Field(default=None, alias="stationPresets")
703
+ station_presets_am: Optional[int] = Field(default=None, alias="stationPresetsAm")
704
+ station_presets_fm: Optional[int] = Field(default=None, alias="stationPresetsFm")
705
+
706
+ # Player specific
707
+ cd_r_rw_compatible: Optional[bool] = Field(default=None, alias="cdRRwCompatible")
708
+ disc_capacity: Optional[int] = Field(default=None, alias="discCapacity")
709
+ dvd_player: Optional[bool] = Field(default=None, alias="dvdPlayer")
710
+ playback_formats: List[PlaybackFormat] = Field(default=[], alias="playbackFormats")
711
+ player_type: Optional[str] = Field(default=None, alias="playerType")
712
+
713
+ # Other connectivity
714
+ built_in_digital_camera: Optional[bool] = Field(
715
+ default=None, alias="builtInDigitalCamera"
716
+ )
717
+ ethernet_port: Optional[bool] = Field(default=None, alias="ethernetPort")
718
+ headphone_jacks: Optional[bool] = Field(default=None, alias="headphoneJacks")
719
+ internet_connectable: Optional[bool] = Field(
720
+ default=None, alias="internetConnectable"
721
+ )
722
+ media_card_slot: Optional[bool] = Field(default=None, alias="mediaCardSlot")
723
+ multiroom_capability: Optional[bool] = Field(
724
+ default=None, alias="multiroomCapability"
725
+ )
726
+ rf_antenna_input: Optional[bool] = Field(default=None, alias="rfAntennaInput")
727
+ usb_port: Optional[bool] = Field(default=None, alias="usbPort")
728
+ wifi_built_in: Optional[bool] = Field(default=None, alias="wifiBuiltIn")
729
+
730
+ # Other features
731
+ collection: Optional[str] = None
732
+ compact_design: Optional[bool] = Field(default=None, alias="compactDesign")
733
+ door_handle_color: Optional[str] = Field(default=None, alias="doorHandleColor")
734
+ drive_capacity_gb: Optional[int] = Field(default=None, alias="driveCapacityGb")
735
+ drive_connectivity: Optional[str] = Field(default=None, alias="driveConnectivity")
736
+ front_facing_camera: Optional[bool] = Field(default=None, alias="frontFacingCamera")
737
+ language_options: List[LanguageOption] = Field(default=[], alias="languageOptions")
738
+ maximum_output_resolution: Optional[str] = Field(
739
+ default=None, alias="maximumOutputResolution"
740
+ )
741
+ mobile_operating_system: Optional[str] = Field(
742
+ default=None, alias="mobileOperatingSystem"
743
+ )
744
+ mount_bracket_vesa_pattern: Optional[str] = Field(
745
+ default=None, alias="mountBracketVesaPattern"
746
+ )
747
+ noise_reduction: Optional[bool] = Field(default=None, alias="noiseReduction")
748
+ on_screen_display: Optional[bool] = Field(default=None, alias="onScreenDisplay")
749
+ power_source: Optional[str] = Field(default=None, alias="powerSource")
750
+ rear_facing_camera: Optional[bool] = Field(default=None, alias="rearFacingCamera")
751
+ remote_control_type: Optional[str] = Field(default=None, alias="remoteControlType")
752
+ scanner_type: Optional[str] = Field(default=None, alias="scannerType")
753
+ service_provider: Optional[str] = Field(default=None, alias="serviceProvider")
754
+ sleep_timer: Optional[bool] = Field(default=None, alias="sleepTimer")
755
+ surface_finish: Optional[str] = Field(default=None, alias="surfaceFinish")
756
+ device_manufacturer: Optional[str] = Field(default=None, alias="deviceManufacturer")
757
+
758
+
759
+ class ProductsResponse(BaseModel):
760
+ """Response containing a list of products with pagination metadata."""
761
+
762
+ model_config = ConfigDict(populate_by_name=True)
763
+
764
+ # Pagination metadata
765
+ from_: int = Field(alias="from")
766
+ to: int
767
+ current_page: int = Field(alias="currentPage")
768
+ total: int
769
+ total_pages: int = Field(alias="totalPages")
770
+ query_time: str = Field(alias="queryTime")
771
+ total_time: str = Field(alias="totalTime")
772
+ canonical_url: str = Field(alias="canonicalUrl")
773
+ partial: bool = False
774
+
775
+ # Products
776
+ products: List[Product]
777
+
778
+
779
+ # Recommendations API Models
780
+
781
+
782
+ class RecommendationCustomerReviews(BaseModel):
783
+ """Customer review information for a recommended product."""
784
+
785
+ model_config = ConfigDict(populate_by_name=True)
786
+
787
+ average_score: Optional[float] = Field(default=None, alias="averageScore")
788
+ count: Optional[int] = None
789
+
790
+
791
+ class RecommendationDescriptions(BaseModel):
792
+ """Description information for a recommended product."""
793
+
794
+ short: Optional[str] = None
795
+
796
+
797
+ class RecommendationImages(BaseModel):
798
+ """Image URLs for a recommended product."""
799
+
800
+ standard: Optional[str] = None
801
+
802
+
803
+ class RecommendationNames(BaseModel):
804
+ """Name information for a recommended product."""
805
+
806
+ title: str
807
+
808
+
809
+ class RecommendationPrices(BaseModel):
810
+ """Price information for a recommended product."""
811
+
812
+ regular: float
813
+ current: float
814
+
815
+
816
+ class RecommendationLinks(BaseModel):
817
+ """Links for a recommended product."""
818
+
819
+ model_config = ConfigDict(populate_by_name=True)
820
+
821
+ product: str
822
+ web: str
823
+ add_to_cart: str = Field(alias="addToCart")
824
+
825
+
826
+ class RecommendedProduct(BaseModel):
827
+ """A recommended product from the Recommendations API."""
828
+
829
+ model_config = ConfigDict(populate_by_name=True)
830
+
831
+ sku: str
832
+ customer_reviews: RecommendationCustomerReviews = Field(alias="customerReviews")
833
+ descriptions: RecommendationDescriptions
834
+ images: RecommendationImages
835
+ names: RecommendationNames
836
+ prices: RecommendationPrices
837
+ links: RecommendationLinks
838
+ rank: int
839
+
840
+
841
+ class RecommendationsContext(BaseModel):
842
+ """Context metadata for recommendations response."""
843
+
844
+ model_config = ConfigDict(populate_by_name=True)
845
+
846
+ canonical_url: str = Field(alias="canonicalUrl")
847
+
848
+
849
+ class RecommendationsResultSet(BaseModel):
850
+ """Result set metadata for recommendations response."""
851
+
852
+ count: int
853
+
854
+
855
+ class RecommendationsMetadata(BaseModel):
856
+ """Metadata for recommendations response."""
857
+
858
+ model_config = ConfigDict(populate_by_name=True)
859
+
860
+ context: RecommendationsContext
861
+ result_set: RecommendationsResultSet = Field(alias="resultSet")
862
+
863
+
864
+ class RecommendationsResponse(BaseModel):
865
+ """Response from Recommendations API endpoints."""
866
+
867
+ metadata: RecommendationsMetadata
868
+ results: List[RecommendedProduct]
869
+
870
+
871
+ # Stores API Models
872
+
873
+
874
+ class StoreDetailedHours(BaseModel):
875
+ """Detailed hours for a specific day."""
876
+
877
+ day: str
878
+ date: date
879
+ open: str
880
+ close: str
881
+
882
+
883
+ class StoreService(BaseModel):
884
+ """A service offered at a store."""
885
+
886
+ service: str
887
+
888
+
889
+ class CatalogStore(BaseModel):
890
+ """A Best Buy store from the Catalog API."""
891
+
892
+ model_config = ConfigDict(populate_by_name=True)
893
+
894
+ # Identification
895
+ store_id: int = Field(alias="storeId")
896
+ store_type: Optional[str] = Field(default=None, alias="storeType")
897
+ location_type: Optional[str] = Field(default=None, alias="locationType")
898
+
899
+ # Names
900
+ name: str
901
+ long_name: Optional[str] = Field(default=None, alias="longName")
902
+
903
+ # Address
904
+ address: Optional[str] = None
905
+ address2: Optional[str] = None
906
+ city: Optional[str] = None
907
+ region: Optional[str] = None
908
+ postal_code: Optional[str] = Field(default=None, alias="postalCode")
909
+ full_postal_code: Optional[str] = Field(default=None, alias="fullPostalCode")
910
+ country: Optional[str] = None
911
+
912
+ # Location
913
+ lat: Optional[float] = None
914
+ lng: Optional[float] = None
915
+ location: Optional[str] = None
916
+ distance: Optional[float] = None
917
+
918
+ # Contact
919
+ phone: Optional[str] = None
920
+
921
+ # Hours
922
+ hours: Optional[str] = None
923
+ hours_am_pm: Optional[str] = Field(default=None, alias="hoursAmPm")
924
+ gmt_offset: Optional[int] = Field(default=None, alias="gmtOffset")
925
+ detailed_hours: List[StoreDetailedHours] = Field(default=[], alias="detailedHours")
926
+
927
+ # Services
928
+ services: List[StoreService] = []
929
+
930
+
931
+ class CatalogStoresResponse(BaseModel):
932
+ """Response containing a list of stores with pagination metadata."""
933
+
934
+ model_config = ConfigDict(populate_by_name=True)
935
+
936
+ # Pagination metadata
937
+ from_: int = Field(alias="from")
938
+ to: int
939
+ current_page: int = Field(alias="currentPage")
940
+ total: int
941
+ total_pages: int = Field(alias="totalPages")
942
+ query_time: str = Field(alias="queryTime")
943
+ total_time: str = Field(alias="totalTime")
944
+ canonical_url: str = Field(alias="canonicalUrl")
945
+ partial: bool = False
946
+
947
+ # Stores
948
+ stores: List[CatalogStore]