etsy-python 1.1.14__tar.gz → 1.2.1__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.
- {etsy_python-1.1.14/etsy_python.egg-info → etsy_python-1.2.1}/PKG-INFO +1 -1
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/_version.py +1 -1
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/Listing.py +1 -1
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Listing.py +166 -17
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingVideo.py +16 -3
- {etsy_python-1.1.14 → etsy_python-1.2.1/etsy_python.egg-info}/PKG-INFO +1 -1
- {etsy_python-1.1.14 → etsy_python-1.2.1}/LICENSE +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/MANIFEST.in +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/README.md +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/auth/OAuth.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/auth/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/common/Env.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/common/Request.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/common/Utils.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/common/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/HolidayPreferences.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/Language.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/ListingInventory.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/ProcessingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/ShippingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/ShopReceipt.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/enums/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/exceptions/BaseAPIException.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/exceptions/RequestException.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/exceptions/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/FileRequest.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/HolidayPreferences.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Miscellaneous.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/ProcessingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Product.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Receipt.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Request.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/ShippingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Shop.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/ShopReturnPolicy.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/Utils.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/models/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/HolidayPreferences.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Listing.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingFile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingImage.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingInventory.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingOffering.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingProduct.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingTranslation.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ListingVariationImages.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Miscellaneous.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Payment.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/PaymentLedgerEntry.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ProcessingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Receipt.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ReceiptTransactions.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Response.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Review.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Session.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ShippingProfile.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Shop.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ShopProductionPartner.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ShopReturnPolicy.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/ShopSection.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/Taxonomy.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/User.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/UserAddress.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/enums/RateLimit.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/enums/Request.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python/v3/resources/enums/__init__.py +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python.egg-info/SOURCES.txt +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python.egg-info/dependency_links.txt +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python.egg-info/requires.txt +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/etsy_python.egg-info/top_level.txt +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/setup.cfg +0 -0
- {etsy_python-1.1.14 → etsy_python-1.2.1}/setup.py +0 -0
|
@@ -17,7 +17,8 @@ from etsy_python.v3.models.FileRequest import FileRequest
|
|
|
17
17
|
_PERSONALIZATION_DEPRECATION_MSG = (
|
|
18
18
|
"is_personalizable, personalization_is_required, "
|
|
19
19
|
"personalization_char_count_max, and personalization_instructions "
|
|
20
|
-
"
|
|
20
|
+
"were removed from createDraftListing and updateListing by the Etsy API "
|
|
21
|
+
"and are no longer sent. "
|
|
21
22
|
"Use the personalization endpoint (update_listing_personalization) "
|
|
22
23
|
"instead. See "
|
|
23
24
|
"https://developers.etsy.com/documentation/tutorials/personalization-migration "
|
|
@@ -30,12 +31,18 @@ def _warn_if_personalization_used(
|
|
|
30
31
|
personalization_is_required: Optional[bool],
|
|
31
32
|
personalization_char_count_max: Optional[int],
|
|
32
33
|
personalization_instructions: Optional[str],
|
|
34
|
+
stacklevel: int = 4,
|
|
33
35
|
) -> None:
|
|
34
|
-
"""Emit DeprecationWarning when a
|
|
36
|
+
"""Emit DeprecationWarning when a removed personalization field is actively set.
|
|
35
37
|
|
|
36
38
|
Falsy values (False, 0, empty string, None) match the API's documented
|
|
37
|
-
defaults and
|
|
38
|
-
trigger the warning.
|
|
39
|
+
defaults and were no-ops even before the fields were removed, so they do
|
|
40
|
+
not trigger the warning.
|
|
41
|
+
|
|
42
|
+
``stacklevel`` counts the frames back to the caller. It defaults to the
|
|
43
|
+
constructor path (this function <- ``_store_personalization`` <- model
|
|
44
|
+
``__init__`` <- caller); the property setters pass 3, being one frame
|
|
45
|
+
shallower.
|
|
39
46
|
"""
|
|
40
47
|
if any([
|
|
41
48
|
is_personalizable,
|
|
@@ -46,11 +53,127 @@ def _warn_if_personalization_used(
|
|
|
46
53
|
warnings.warn(
|
|
47
54
|
_PERSONALIZATION_DEPRECATION_MSG,
|
|
48
55
|
DeprecationWarning,
|
|
49
|
-
stacklevel=
|
|
56
|
+
stacklevel=stacklevel,
|
|
57
|
+
)
|
|
58
|
+
|
|
59
|
+
|
|
60
|
+
class _PersonalizationFieldsMixin:
|
|
61
|
+
"""Accessors for the personalization fields Etsy removed from listings.
|
|
62
|
+
|
|
63
|
+
Etsy dropped these four fields from the createDraftListing and
|
|
64
|
+
updateListing request bodies (2026-09 spec). The constructor keyword
|
|
65
|
+
arguments are kept so existing callers don't break, but the values are
|
|
66
|
+
stored under underscore-prefixed names, which ``todict`` excludes from
|
|
67
|
+
serialization -- so they are never sent on the wire.
|
|
68
|
+
|
|
69
|
+
The properties below keep both attribute reads and writes working. A write
|
|
70
|
+
stores the value and warns, exactly like passing the keyword argument: it
|
|
71
|
+
never reaches the API either way. Remove the keyword arguments and this
|
|
72
|
+
mixin in the next major version.
|
|
73
|
+
"""
|
|
74
|
+
|
|
75
|
+
@property
|
|
76
|
+
def is_personalizable(self) -> Optional[bool]:
|
|
77
|
+
return self._is_personalizable
|
|
78
|
+
|
|
79
|
+
@is_personalizable.setter
|
|
80
|
+
def is_personalizable(self, value: Optional[bool]) -> None:
|
|
81
|
+
self._is_personalizable = value
|
|
82
|
+
_warn_if_personalization_used(value, None, None, None, stacklevel=3)
|
|
83
|
+
|
|
84
|
+
@property
|
|
85
|
+
def personalization_is_required(self) -> Optional[bool]:
|
|
86
|
+
return self._personalization_is_required
|
|
87
|
+
|
|
88
|
+
@personalization_is_required.setter
|
|
89
|
+
def personalization_is_required(self, value: Optional[bool]) -> None:
|
|
90
|
+
self._personalization_is_required = value
|
|
91
|
+
_warn_if_personalization_used(None, value, None, None, stacklevel=3)
|
|
92
|
+
|
|
93
|
+
@property
|
|
94
|
+
def personalization_char_count_max(self) -> Optional[int]:
|
|
95
|
+
return self._personalization_char_count_max
|
|
96
|
+
|
|
97
|
+
@personalization_char_count_max.setter
|
|
98
|
+
def personalization_char_count_max(self, value: Optional[int]) -> None:
|
|
99
|
+
self._personalization_char_count_max = value
|
|
100
|
+
_warn_if_personalization_used(None, None, value, None, stacklevel=3)
|
|
101
|
+
|
|
102
|
+
@property
|
|
103
|
+
def personalization_instructions(self) -> Optional[str]:
|
|
104
|
+
return self._personalization_instructions
|
|
105
|
+
|
|
106
|
+
@personalization_instructions.setter
|
|
107
|
+
def personalization_instructions(self, value: Optional[str]) -> None:
|
|
108
|
+
self._personalization_instructions = value
|
|
109
|
+
_warn_if_personalization_used(None, None, None, value, stacklevel=3)
|
|
110
|
+
|
|
111
|
+
def _store_personalization(
|
|
112
|
+
self,
|
|
113
|
+
is_personalizable: Optional[bool],
|
|
114
|
+
personalization_is_required: Optional[bool],
|
|
115
|
+
personalization_char_count_max: Optional[int],
|
|
116
|
+
personalization_instructions: Optional[str],
|
|
117
|
+
) -> None:
|
|
118
|
+
self._is_personalizable = is_personalizable
|
|
119
|
+
self._personalization_is_required = personalization_is_required
|
|
120
|
+
self._personalization_char_count_max = personalization_char_count_max
|
|
121
|
+
self._personalization_instructions = personalization_instructions
|
|
122
|
+
_warn_if_personalization_used(
|
|
123
|
+
is_personalizable,
|
|
124
|
+
personalization_is_required,
|
|
125
|
+
personalization_char_count_max,
|
|
126
|
+
personalization_instructions,
|
|
50
127
|
)
|
|
51
128
|
|
|
52
129
|
|
|
53
|
-
|
|
130
|
+
#: EU commercial guarantee / GPSR fields (ECGT), shared by createDraftListing
|
|
131
|
+
#: and updateListing. All are optional and nullable. Etsy silently ignores them
|
|
132
|
+
#: for sellers who are not eligible EU traders. ``ecgt_software_update_details``
|
|
133
|
+
#: is ignored for physical listings; the other six are ignored for digital ones.
|
|
134
|
+
#: ``ecgt_garan_brand``, ``ecgt_garan_model``, ``ecgt_garan_years`` and
|
|
135
|
+
#: ``ecgt_garan_guarantee_details`` are required *together* -- Etsy enforces
|
|
136
|
+
#: that server-side and rejects a partial set.
|
|
137
|
+
ECGT_FIELDS = (
|
|
138
|
+
"ecgt_garan_brand",
|
|
139
|
+
"ecgt_garan_model",
|
|
140
|
+
"ecgt_garan_years",
|
|
141
|
+
"ecgt_garan_guarantee_details",
|
|
142
|
+
"ecgt_other_commercial_guarantee_details",
|
|
143
|
+
"ecgt_after_sales_service_info",
|
|
144
|
+
"ecgt_software_update_details",
|
|
145
|
+
)
|
|
146
|
+
|
|
147
|
+
|
|
148
|
+
class _ECGTFieldsMixin:
|
|
149
|
+
"""Storage for the EU commercial guarantee (ECGT) listing fields.
|
|
150
|
+
|
|
151
|
+
Both listing request models accept the same seven fields, so the
|
|
152
|
+
assignment lives here instead of being duplicated. See ``ECGT_FIELDS``.
|
|
153
|
+
"""
|
|
154
|
+
|
|
155
|
+
def _store_ecgt(
|
|
156
|
+
self,
|
|
157
|
+
ecgt_garan_brand: Optional[str],
|
|
158
|
+
ecgt_garan_model: Optional[str],
|
|
159
|
+
ecgt_garan_years: Optional[int],
|
|
160
|
+
ecgt_garan_guarantee_details: Optional[str],
|
|
161
|
+
ecgt_other_commercial_guarantee_details: Optional[str],
|
|
162
|
+
ecgt_after_sales_service_info: Optional[str],
|
|
163
|
+
ecgt_software_update_details: Optional[str],
|
|
164
|
+
) -> None:
|
|
165
|
+
self.ecgt_garan_brand = ecgt_garan_brand
|
|
166
|
+
self.ecgt_garan_model = ecgt_garan_model
|
|
167
|
+
self.ecgt_garan_years = ecgt_garan_years
|
|
168
|
+
self.ecgt_garan_guarantee_details = ecgt_garan_guarantee_details
|
|
169
|
+
self.ecgt_other_commercial_guarantee_details = (
|
|
170
|
+
ecgt_other_commercial_guarantee_details
|
|
171
|
+
)
|
|
172
|
+
self.ecgt_after_sales_service_info = ecgt_after_sales_service_info
|
|
173
|
+
self.ecgt_software_update_details = ecgt_software_update_details
|
|
174
|
+
|
|
175
|
+
|
|
176
|
+
class CreateDraftListingRequest(_PersonalizationFieldsMixin, _ECGTFieldsMixin, Request):
|
|
54
177
|
nullable = [
|
|
55
178
|
"shipping_profile_id",
|
|
56
179
|
"return_policy_id",
|
|
@@ -69,6 +192,7 @@ class CreateDraftListingRequest(Request):
|
|
|
69
192
|
"production_partner_ids",
|
|
70
193
|
"image_ids",
|
|
71
194
|
"readiness_state_id",
|
|
195
|
+
*ECGT_FIELDS,
|
|
72
196
|
]
|
|
73
197
|
mandatory = [
|
|
74
198
|
"quantity",
|
|
@@ -115,6 +239,13 @@ class CreateDraftListingRequest(Request):
|
|
|
115
239
|
is_taxable: Optional[bool] = None,
|
|
116
240
|
listing_type: Optional[Type] = None,
|
|
117
241
|
readiness_state_id: Optional[int] = None,
|
|
242
|
+
ecgt_garan_brand: Optional[str] = None,
|
|
243
|
+
ecgt_garan_model: Optional[str] = None,
|
|
244
|
+
ecgt_garan_years: Optional[int] = None,
|
|
245
|
+
ecgt_garan_guarantee_details: Optional[str] = None,
|
|
246
|
+
ecgt_other_commercial_guarantee_details: Optional[str] = None,
|
|
247
|
+
ecgt_after_sales_service_info: Optional[str] = None,
|
|
248
|
+
ecgt_software_update_details: Optional[str] = None,
|
|
118
249
|
):
|
|
119
250
|
self.quantity = quantity
|
|
120
251
|
self.title = title
|
|
@@ -137,11 +268,7 @@ class CreateDraftListingRequest(Request):
|
|
|
137
268
|
self.item_height = item_height
|
|
138
269
|
self.item_weight_unit = item_weight_unit
|
|
139
270
|
self.item_dimensions_unit = item_dimensions_unit
|
|
140
|
-
self.
|
|
141
|
-
self.personalization_is_required = personalization_is_required
|
|
142
|
-
self.personalization_char_count_max = personalization_char_count_max
|
|
143
|
-
self.personalization_instructions = personalization_instructions
|
|
144
|
-
_warn_if_personalization_used(
|
|
271
|
+
self._store_personalization(
|
|
145
272
|
is_personalizable,
|
|
146
273
|
personalization_is_required,
|
|
147
274
|
personalization_char_count_max,
|
|
@@ -155,13 +282,22 @@ class CreateDraftListingRequest(Request):
|
|
|
155
282
|
self.is_taxable = is_taxable
|
|
156
283
|
self._type = listing_type
|
|
157
284
|
self.readiness_state_id = readiness_state_id
|
|
285
|
+
self._store_ecgt(
|
|
286
|
+
ecgt_garan_brand,
|
|
287
|
+
ecgt_garan_model,
|
|
288
|
+
ecgt_garan_years,
|
|
289
|
+
ecgt_garan_guarantee_details,
|
|
290
|
+
ecgt_other_commercial_guarantee_details,
|
|
291
|
+
ecgt_after_sales_service_info,
|
|
292
|
+
ecgt_software_update_details,
|
|
293
|
+
)
|
|
158
294
|
super().__init__(
|
|
159
295
|
nullable=CreateDraftListingRequest.nullable,
|
|
160
296
|
mandatory=CreateDraftListingRequest.mandatory,
|
|
161
297
|
)
|
|
162
298
|
|
|
163
299
|
|
|
164
|
-
class UpdateListingRequest(Request):
|
|
300
|
+
class UpdateListingRequest(_PersonalizationFieldsMixin, _ECGTFieldsMixin, Request):
|
|
165
301
|
nullable: List[str] = [
|
|
166
302
|
"materials",
|
|
167
303
|
"shipping_profile_id",
|
|
@@ -177,6 +313,7 @@ class UpdateListingRequest(Request):
|
|
|
177
313
|
"featured_rank",
|
|
178
314
|
"production_partner_ids",
|
|
179
315
|
"_type",
|
|
316
|
+
*ECGT_FIELDS,
|
|
180
317
|
]
|
|
181
318
|
|
|
182
319
|
mandatory: List[str] = []
|
|
@@ -211,6 +348,13 @@ class UpdateListingRequest(Request):
|
|
|
211
348
|
is_supply: Optional[bool] = None,
|
|
212
349
|
production_partner_ids: Optional[List[int]] = None,
|
|
213
350
|
listing_type: Optional[Type] = None,
|
|
351
|
+
ecgt_garan_brand: Optional[str] = None,
|
|
352
|
+
ecgt_garan_model: Optional[str] = None,
|
|
353
|
+
ecgt_garan_years: Optional[int] = None,
|
|
354
|
+
ecgt_garan_guarantee_details: Optional[str] = None,
|
|
355
|
+
ecgt_other_commercial_guarantee_details: Optional[str] = None,
|
|
356
|
+
ecgt_after_sales_service_info: Optional[str] = None,
|
|
357
|
+
ecgt_software_update_details: Optional[str] = None,
|
|
214
358
|
):
|
|
215
359
|
self.image_ids = image_ids
|
|
216
360
|
self.title = title
|
|
@@ -232,11 +376,7 @@ class UpdateListingRequest(Request):
|
|
|
232
376
|
self.who_made = who_made
|
|
233
377
|
self.when_made = when_made
|
|
234
378
|
self.featured_rank = featured_rank
|
|
235
|
-
self.
|
|
236
|
-
self.personalization_is_required = personalization_is_required
|
|
237
|
-
self.personalization_char_count_max = personalization_char_count_max
|
|
238
|
-
self.personalization_instructions = personalization_instructions
|
|
239
|
-
_warn_if_personalization_used(
|
|
379
|
+
self._store_personalization(
|
|
240
380
|
is_personalizable,
|
|
241
381
|
personalization_is_required,
|
|
242
382
|
personalization_char_count_max,
|
|
@@ -246,6 +386,15 @@ class UpdateListingRequest(Request):
|
|
|
246
386
|
self.is_supply = is_supply
|
|
247
387
|
self.production_partner_ids = production_partner_ids
|
|
248
388
|
self._type = listing_type
|
|
389
|
+
self._store_ecgt(
|
|
390
|
+
ecgt_garan_brand,
|
|
391
|
+
ecgt_garan_model,
|
|
392
|
+
ecgt_garan_years,
|
|
393
|
+
ecgt_garan_guarantee_details,
|
|
394
|
+
ecgt_other_commercial_guarantee_details,
|
|
395
|
+
ecgt_after_sales_service_info,
|
|
396
|
+
ecgt_software_update_details,
|
|
397
|
+
)
|
|
249
398
|
super().__init__(
|
|
250
399
|
nullable=UpdateListingRequest.nullable,
|
|
251
400
|
mandatory=UpdateListingRequest.mandatory,
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
from dataclasses import dataclass
|
|
2
|
-
from typing import Union
|
|
2
|
+
from typing import Optional, Union
|
|
3
3
|
|
|
4
4
|
from etsy_python.v3.exceptions.RequestException import RequestException
|
|
5
5
|
from etsy_python.v3.models.Listing import UpdateListingVideoRequest
|
|
@@ -29,9 +29,22 @@ class ListingVideoResource:
|
|
|
29
29
|
return self.session.make_request(endpoint)
|
|
30
30
|
|
|
31
31
|
def upload_listing_video(
|
|
32
|
-
self,
|
|
32
|
+
self,
|
|
33
|
+
shop_id: int,
|
|
34
|
+
listing_id: int,
|
|
35
|
+
listing_video: UpdateListingVideoRequest,
|
|
36
|
+
is_multi_video: Optional[bool] = None,
|
|
33
37
|
) -> Union[Response, RequestException]:
|
|
38
|
+
"""Upload a video to a listing.
|
|
39
|
+
|
|
40
|
+
Pass ``is_multi_video=True`` to keep existing videos on the listing.
|
|
41
|
+
Omitting it preserves the former single-video behaviour, where the
|
|
42
|
+
upload replaces any video already attached.
|
|
43
|
+
"""
|
|
34
44
|
endpoint = f"/shops/{shop_id}/listings/{listing_id}/videos"
|
|
35
45
|
return self.session.make_request(
|
|
36
|
-
endpoint,
|
|
46
|
+
endpoint,
|
|
47
|
+
method=Method.POST,
|
|
48
|
+
payload=listing_video,
|
|
49
|
+
query_params={"is_multi_video": is_multi_video},
|
|
37
50
|
)
|
|
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
|
|
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
|
|
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
|