etsy-python 1.0.20__tar.gz → 1.1.0__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 (78) hide show
  1. etsy_python-1.1.0/MANIFEST.in +13 -0
  2. {etsy_python-1.0.20 → etsy_python-1.1.0}/PKG-INFO +50 -16
  3. {etsy_python-1.0.20 → etsy_python-1.1.0}/README.md +49 -15
  4. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/_version.py +1 -1
  5. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/common/Utils.py +9 -7
  6. etsy_python-1.1.0/etsy_python/v3/enums/HolidayPreferences.py +42 -0
  7. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/Listing.py +12 -4
  8. etsy_python-1.1.0/etsy_python/v3/enums/ProcessingProfile.py +11 -0
  9. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/ShippingProfile.py +2 -2
  10. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Listing.py +21 -1
  11. etsy_python-1.1.0/etsy_python/v3/models/ProcessingProfile.py +61 -0
  12. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Request.py +2 -1
  13. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/ShippingProfile.py +11 -5
  14. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/HolidayPreferences.py +1 -1
  15. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Listing.py +94 -27
  16. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingInventory.py +8 -4
  17. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingOffering.py +5 -3
  18. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingProduct.py +5 -3
  19. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Payment.py +18 -5
  20. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/PaymentLedgerEntry.py +2 -2
  21. etsy_python-1.1.0/etsy_python/v3/resources/ProcessingProfile.py +56 -0
  22. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Receipt.py +14 -6
  23. etsy_python-1.1.0/etsy_python/v3/resources/ReceiptTransactions.py +52 -0
  24. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Review.py +4 -4
  25. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Session.py +2 -2
  26. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ShippingProfile.py +20 -5
  27. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Shop.py +2 -2
  28. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/UserAddress.py +2 -2
  29. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/__init__.py +2 -0
  30. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python.egg-info/PKG-INFO +50 -16
  31. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python.egg-info/SOURCES.txt +5 -2
  32. {etsy_python-1.0.20 → etsy_python-1.1.0}/setup.py +1 -1
  33. etsy_python-1.0.20/etsy_python/v3/enums/HolidayPreferences.py +0 -41
  34. etsy_python-1.0.20/etsy_python/v3/resources/ReceiptTransactions.py +0 -37
  35. etsy_python-1.0.20/etsy_python/v3/tests/__init__.py +0 -0
  36. {etsy_python-1.0.20 → etsy_python-1.1.0}/LICENSE +0 -0
  37. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/__init__.py +0 -0
  38. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/__init__.py +0 -0
  39. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/auth/OAuth.py +0 -0
  40. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/auth/__init__.py +0 -0
  41. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/common/Env.py +0 -0
  42. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/common/Request.py +0 -0
  43. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/common/__init__.py +0 -0
  44. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/Language.py +0 -0
  45. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/ListingInventory.py +0 -0
  46. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/ShopReceipt.py +0 -0
  47. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/enums/__init__.py +0 -0
  48. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/exceptions/BaseAPIException.py +0 -0
  49. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/exceptions/RequestException.py +0 -0
  50. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/exceptions/__init__.py +0 -0
  51. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/FileRequest.py +0 -0
  52. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/HolidayPreferences.py +0 -0
  53. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Miscellaneous.py +0 -0
  54. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Product.py +0 -0
  55. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Receipt.py +0 -0
  56. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Shop.py +0 -0
  57. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/ShopReturnPolicy.py +0 -0
  58. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/Utils.py +0 -0
  59. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/models/__init__.py +0 -0
  60. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingFile.py +0 -0
  61. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingImage.py +0 -0
  62. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingTranslation.py +0 -0
  63. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingVariationImages.py +0 -0
  64. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ListingVideo.py +0 -0
  65. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Miscellaneous.py +0 -0
  66. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Response.py +0 -0
  67. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ShopProductionPartner.py +0 -0
  68. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ShopReturnPolicy.py +0 -0
  69. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/ShopSection.py +0 -0
  70. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/Taxonomy.py +0 -0
  71. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/User.py +0 -0
  72. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/enums/RateLimit.py +0 -0
  73. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/enums/Request.py +0 -0
  74. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python/v3/resources/enums/__init__.py +0 -0
  75. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python.egg-info/dependency_links.txt +0 -0
  76. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python.egg-info/requires.txt +0 -0
  77. {etsy_python-1.0.20 → etsy_python-1.1.0}/etsy_python.egg-info/top_level.txt +0 -0
  78. {etsy_python-1.0.20 → etsy_python-1.1.0}/setup.cfg +0 -0
@@ -0,0 +1,13 @@
1
+ include LICENSE
2
+ include README.md
3
+
4
+ # Exclude maintenance and development files
5
+ prune scripts
6
+ prune specs
7
+ prune docs
8
+ prune .claude
9
+ prune .github
10
+ prune tests
11
+
12
+ exclude .bumpversion.cfg
13
+ exclude .pre-commit-config.yaml
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: etsy-python
3
- Version: 1.0.20
3
+ Version: 1.1.0
4
4
  Summary: Etsy API Client Library for Python
5
5
  Author: Amit Ray
6
6
  Author-email: mail@amitray.dev
@@ -328,19 +328,25 @@ The SDK provides comprehensive coverage of Etsy API v3 resources:
328
328
  - **Listing** - Create, read, update, delete listings
329
329
  - **Shop** - Manage shop information and settings
330
330
  - **Receipt** - Handle orders and transactions
331
+ - **ReceiptTransactions** - Individual transaction details
331
332
  - **User** - User profiles and addresses
332
- - **ShippingProfile** - Configure shipping options
333
+ - **UserAddress** - User address management
334
+ - **ShippingProfile** - Configure shipping options and destinations
333
335
 
334
336
  ### Media Resources
335
337
 
336
338
  - **ListingImage** - Upload and manage listing images
337
339
  - **ListingVideo** - Upload and manage listing videos
338
340
  - **ListingFile** - Digital file management
341
+ - **ListingVariationImages** - Variation-specific images
339
342
 
340
343
  ### Commerce Resources
341
344
 
342
345
  - **ListingInventory** - Stock and SKU management
343
- - **Payment** - Payment processing and ledger entries
346
+ - **ListingOffering** - Product offering details
347
+ - **ListingProduct** - Product variant management
348
+ - **Payment** - Payment processing
349
+ - **PaymentLedgerEntry** - Payment ledger entries
344
350
  - **Review** - Customer reviews management
345
351
 
346
352
  ### Shop Management
@@ -348,6 +354,14 @@ The SDK provides comprehensive coverage of Etsy API v3 resources:
348
354
  - **ShopSection** - Organize listings into sections
349
355
  - **ShopReturnPolicy** - Define return policies
350
356
  - **ShopProductionPartner** - Manage production partners
357
+ - **HolidayPreferences** - Shop holiday schedule
358
+ - **ProcessingProfile** - Processing time profiles
359
+
360
+ ### Taxonomy & Translation
361
+
362
+ - **BuyerTaxonomy** / **SellerTaxonomy** - Product categories and attributes
363
+ - **ListingTranslation** - Listing localization
364
+ - **Miscellaneous** - Ping and other utility endpoints
351
365
 
352
366
  ## Error Handling
353
367
 
@@ -383,16 +397,24 @@ export ETSY_ENV=PROD
383
397
  ```
384
398
  etsy-python-sdk/
385
399
  ├── etsy_python/
400
+ │ ├── _version.py # Single source of truth for version
386
401
  │ └── v3/
387
- │ ├── auth/ # OAuth authentication
388
- │ ├── common/ # Shared utilities
389
- │ ├── enums/ # API enum definitions
390
- │ ├── exceptions/ # Custom exceptions
391
- │ ├── models/ # Request/response models
392
- │ └── resources/ # API endpoint implementations
393
- ├── setup.py # Package configuration
394
- ├── LICENSE # MIT License
395
- └── README.md # Documentation
402
+ │ ├── auth/ # OAuth 2.0 PKCE authentication
403
+ │ ├── common/ # Shared utilities and HTTP constants
404
+ │ ├── enums/ # Type-safe API parameter constants
405
+ │ ├── exceptions/ # Custom exceptions with rate limit info
406
+ │ ├── models/ # Request data models with validation
407
+ │ └── resources/ # ~28 API endpoint resource classes
408
+ ├── tests/ # pytest test suite
409
+ │ └── fixtures/ # Shared test fixtures and mock responses
410
+ ├── scripts/ # Maintenance and release scripts
411
+ ├── specs/ # OAS spec files and audit reports
412
+ ├── .github/
413
+ │ ├── workflows/ # CI/CD and PR automation
414
+ │ └── CODEOWNERS # Required reviewers for sensitive files
415
+ ├── setup.py # Package configuration
416
+ ├── requirements-dev.txt # Development/testing dependencies
417
+ └── README.md # Documentation
396
418
  ```
397
419
 
398
420
  ## Contributing
@@ -459,16 +481,28 @@ python scripts/release.py patch --no-push
459
481
  4. Install dependencies:
460
482
  ```bash
461
483
  pip install -r etsy_python/requirements.txt
484
+ pip install -r requirements-dev.txt
485
+ ```
486
+ 5. Run the test suite:
487
+ ```bash
488
+ pytest -v
489
+ pytest --cov=etsy_python --cov-report=term-missing
462
490
  ```
463
- 5. Create a feature branch:
491
+ 6. Create a feature branch:
464
492
  ```bash
465
493
  git checkout -b feature/your-feature-name
466
494
  ```
467
- 6. Make your changes and commit:
495
+ 7. Make your changes and commit:
468
496
  ```bash
469
- git commit -m "Add your feature"
497
+ git commit -m "feat: add your feature"
470
498
  ```
471
- 7. Push and create a pull request
499
+ 8. Push and create a pull request
500
+
501
+ ### CI on Pull Requests
502
+
503
+ Pull requests automatically trigger:
504
+ - **pr-tests.yml** — Runs the full test suite with coverage reporting (posts/updates a comment on the PR)
505
+ - **pr-coverage.yml** — SDK coverage audit against the Etsy OAS spec (triggered by the `sdk-check` label)
472
506
 
473
507
  ## Support
474
508
 
@@ -307,19 +307,25 @@ The SDK provides comprehensive coverage of Etsy API v3 resources:
307
307
  - **Listing** - Create, read, update, delete listings
308
308
  - **Shop** - Manage shop information and settings
309
309
  - **Receipt** - Handle orders and transactions
310
+ - **ReceiptTransactions** - Individual transaction details
310
311
  - **User** - User profiles and addresses
311
- - **ShippingProfile** - Configure shipping options
312
+ - **UserAddress** - User address management
313
+ - **ShippingProfile** - Configure shipping options and destinations
312
314
 
313
315
  ### Media Resources
314
316
 
315
317
  - **ListingImage** - Upload and manage listing images
316
318
  - **ListingVideo** - Upload and manage listing videos
317
319
  - **ListingFile** - Digital file management
320
+ - **ListingVariationImages** - Variation-specific images
318
321
 
319
322
  ### Commerce Resources
320
323
 
321
324
  - **ListingInventory** - Stock and SKU management
322
- - **Payment** - Payment processing and ledger entries
325
+ - **ListingOffering** - Product offering details
326
+ - **ListingProduct** - Product variant management
327
+ - **Payment** - Payment processing
328
+ - **PaymentLedgerEntry** - Payment ledger entries
323
329
  - **Review** - Customer reviews management
324
330
 
325
331
  ### Shop Management
@@ -327,6 +333,14 @@ The SDK provides comprehensive coverage of Etsy API v3 resources:
327
333
  - **ShopSection** - Organize listings into sections
328
334
  - **ShopReturnPolicy** - Define return policies
329
335
  - **ShopProductionPartner** - Manage production partners
336
+ - **HolidayPreferences** - Shop holiday schedule
337
+ - **ProcessingProfile** - Processing time profiles
338
+
339
+ ### Taxonomy & Translation
340
+
341
+ - **BuyerTaxonomy** / **SellerTaxonomy** - Product categories and attributes
342
+ - **ListingTranslation** - Listing localization
343
+ - **Miscellaneous** - Ping and other utility endpoints
330
344
 
331
345
  ## Error Handling
332
346
 
@@ -362,16 +376,24 @@ export ETSY_ENV=PROD
362
376
  ```
363
377
  etsy-python-sdk/
364
378
  ├── etsy_python/
379
+ │ ├── _version.py # Single source of truth for version
365
380
  │ └── v3/
366
- │ ├── auth/ # OAuth authentication
367
- │ ├── common/ # Shared utilities
368
- │ ├── enums/ # API enum definitions
369
- │ ├── exceptions/ # Custom exceptions
370
- │ ├── models/ # Request/response models
371
- │ └── resources/ # API endpoint implementations
372
- ├── setup.py # Package configuration
373
- ├── LICENSE # MIT License
374
- └── README.md # Documentation
381
+ │ ├── auth/ # OAuth 2.0 PKCE authentication
382
+ │ ├── common/ # Shared utilities and HTTP constants
383
+ │ ├── enums/ # Type-safe API parameter constants
384
+ │ ├── exceptions/ # Custom exceptions with rate limit info
385
+ │ ├── models/ # Request data models with validation
386
+ │ └── resources/ # ~28 API endpoint resource classes
387
+ ├── tests/ # pytest test suite
388
+ │ └── fixtures/ # Shared test fixtures and mock responses
389
+ ├── scripts/ # Maintenance and release scripts
390
+ ├── specs/ # OAS spec files and audit reports
391
+ ├── .github/
392
+ │ ├── workflows/ # CI/CD and PR automation
393
+ │ └── CODEOWNERS # Required reviewers for sensitive files
394
+ ├── setup.py # Package configuration
395
+ ├── requirements-dev.txt # Development/testing dependencies
396
+ └── README.md # Documentation
375
397
  ```
376
398
 
377
399
  ## Contributing
@@ -438,16 +460,28 @@ python scripts/release.py patch --no-push
438
460
  4. Install dependencies:
439
461
  ```bash
440
462
  pip install -r etsy_python/requirements.txt
463
+ pip install -r requirements-dev.txt
464
+ ```
465
+ 5. Run the test suite:
466
+ ```bash
467
+ pytest -v
468
+ pytest --cov=etsy_python --cov-report=term-missing
441
469
  ```
442
- 5. Create a feature branch:
470
+ 6. Create a feature branch:
443
471
  ```bash
444
472
  git checkout -b feature/your-feature-name
445
473
  ```
446
- 6. Make your changes and commit:
474
+ 7. Make your changes and commit:
447
475
  ```bash
448
- git commit -m "Add your feature"
476
+ git commit -m "feat: add your feature"
449
477
  ```
450
- 7. Push and create a pull request
478
+ 8. Push and create a pull request
479
+
480
+ ### CI on Pull Requests
481
+
482
+ Pull requests automatically trigger:
483
+ - **pr-tests.yml** — Runs the full test suite with coverage reporting (posts/updates a comment on the PR)
484
+ - **pr-coverage.yml** — SDK coverage audit against the Etsy OAS spec (triggered by the `sdk-check` label)
451
485
 
452
486
  ## Support
453
487
 
@@ -1,3 +1,3 @@
1
1
  """Version information for etsy-python package."""
2
2
 
3
- __version__ = "1.0.20"
3
+ __version__ = "1.1.0"
@@ -2,14 +2,15 @@ from enum import Enum
2
2
  from typing import Any, Dict, List, Optional
3
3
 
4
4
 
5
- def generate_get_uri(uri: str, **kwargs: Dict[str, Any]) -> str:
6
- if kwargs == {} or kwargs is None:
5
+ def generate_get_uri(uri: str, params: Optional[Dict[str, Any]] = None) -> str:
6
+ if not params:
7
7
  return uri
8
- params = "&".join(
9
- [f"{key}={value}" for key, value in kwargs.items() if value is not None]
8
+ formatted = "&".join(
9
+ f"{key}={str(value).lower() if isinstance(value, bool) else value}"
10
+ for key, value in params.items()
11
+ if value is not None
10
12
  )
11
- uri = f"{uri}?{params}" if params != "" else uri
12
- return uri
13
+ return f"{uri}?{formatted}" if formatted else uri
13
14
 
14
15
 
15
16
  def todict(
@@ -31,9 +32,10 @@ def todict(
31
32
  elif hasattr(obj, "__dict__"):
32
33
  data = dict(
33
34
  [
35
+ # _type -> "type": avoids shadowing Python's builtin in model attrs
34
36
  ("type" if key == "_type" else key, todict(value, classkey))
35
37
  if key not in nullable
36
- and (value not in [[], "" or 0] or isinstance(value, bool))
38
+ or (value != [] and value != "" and (value != 0 or isinstance(value, bool)))
37
39
  else (key, None)
38
40
  for key, value in obj.__dict__.items()
39
41
  if not callable(value)
@@ -0,0 +1,42 @@
1
+ from enum import Enum
2
+
3
+ """
4
+ Reference:
5
+ Official Documentation: https://developer.etsy.com/documentation/tutorials/fulfillment/#country-holidays
6
+ """
7
+
8
+ class HOLIDAYS(Enum):
9
+ """
10
+ # Note:
11
+ Integer values from 1 to 105 are supported by Etsy based on selected regions.
12
+ Use US_HOLIDAYS or CA_HOLIDAYS for named constants, or pass integer IDs directly
13
+ for holidays not yet mapped to named constants.
14
+ """
15
+ pass
16
+
17
+ class US_HOLIDAYS(Enum):
18
+ NEW_YEARS_DAY = 1
19
+ MARTIN_LUTHER_KING_JR_DAY = 2
20
+ PRESIDENTS_DAY = 3
21
+ MEMORIAL_DAY = 4
22
+ JUNETEENTH = 5
23
+ INDEPENDENCE_DAY = 6
24
+ LABOR_DAY = 7
25
+ COLUMBUS_DAY = 8
26
+ VETERANS_DAY = 9
27
+ THANKSGIVING_DAY = 10
28
+ CHRISTMAS_DAY = 11
29
+
30
+ class CA_HOLIDAYS(Enum):
31
+ GOOD_FRIDAY = 12
32
+ EASTER = 13
33
+ VICTORIA_DAY = 14
34
+ CANADA_DAY = 15
35
+ TRUTH_AND_RECONCILIATION_DAY = 16
36
+ REMEMBRANCE_DAY = 17
37
+ CIVIC_HOLIDAY = 18
38
+ BOXING_DAY = 19
39
+ NEW_YEARS_DAY = 20
40
+ LABOR_DAY = 21
41
+ THANKSGIVING_DAY = 22
42
+ CHRISTMAS_DAY = 23
@@ -9,11 +9,11 @@ class WhoMade(Enum):
9
9
 
10
10
  class WhenMade(Enum):
11
11
  MADE_TO_ORDER = "made_to_order"
12
- TWENTY_TWENTIES = "2020_2025"
12
+ TWENTY_TWENTIES = "2020_2026"
13
13
  TWENTY_TENS = "2010_2019"
14
- TWENTY_OH_SIX_TO_NINE = "2006_2009"
15
- BEFORE_2006 = "before_2006"
16
- TWO_THOUSAND_TO_FIVE = "2000_2005"
14
+ TWENTY_OH_SEVEN_TO_NINE = "2007_2009"
15
+ BEFORE_2007 = "before_2007"
16
+ TWO_THOUSAND_TO_SIX = "2000_2006"
17
17
  NINETEEN_NINETIES = "1990s"
18
18
  NINETEEN_EIGHTIES = "1980s"
19
19
  NINETEEN_SEVENTIES = "1970s"
@@ -58,6 +58,14 @@ class State(Enum):
58
58
  SOLD_OUT = "sold_out"
59
59
  DRAFT = "draft"
60
60
  EXPIRED = "expired"
61
+ REMOVED = "removed"
62
+
63
+
64
+ class VideoState(Enum):
65
+ ACTIVE = "active"
66
+ INACTIVE = "inactive"
67
+ DELETED = "deleted"
68
+ FLAGGED = "flagged"
61
69
 
62
70
 
63
71
  class SortOn(Enum):
@@ -0,0 +1,11 @@
1
+ from enum import Enum
2
+
3
+
4
+ class ReadinessState(Enum):
5
+ READY_TO_SHIP = "ready_to_ship"
6
+ MADE_TO_ORDER = "made_to_order"
7
+
8
+
9
+ class ProcessingTimeUnit(Enum):
10
+ DAYS = "days"
11
+ WEEKS = "weeks"
@@ -13,8 +13,8 @@ class DestinationRegion(Enum):
13
13
 
14
14
 
15
15
  class Type(Enum):
16
- ZERO = "0" # Domestic Shipping
17
- ONE = "1" # International Shipping
16
+ ZERO = 0 # Domestic Shipping
17
+ ONE = 1 # International Shipping
18
18
 
19
19
 
20
20
  class Providers(Enum):
@@ -31,6 +31,7 @@ class CreateDraftListingRequest(Request):
31
31
  "item_dimensions_unit",
32
32
  "production_partner_ids",
33
33
  "image_ids",
34
+ "readiness_state_id",
34
35
  ]
35
36
  mandatory = [
36
37
  "quantity",
@@ -76,6 +77,7 @@ class CreateDraftListingRequest(Request):
76
77
  should_auto_renew: Optional[bool] = None,
77
78
  is_taxable: Optional[bool] = None,
78
79
  listing_type: Optional[Type] = None,
80
+ readiness_state_id: Optional[int] = None,
79
81
  ):
80
82
  self.quantity = quantity
81
83
  self.title = title
@@ -109,6 +111,7 @@ class CreateDraftListingRequest(Request):
109
111
  self.should_auto_renew = should_auto_renew
110
112
  self.is_taxable = is_taxable
111
113
  self._type = listing_type
114
+ self.readiness_state_id = readiness_state_id
112
115
  super().__init__(
113
116
  nullable=CreateDraftListingRequest.nullable,
114
117
  mandatory=CreateDraftListingRequest.mandatory,
@@ -201,7 +204,7 @@ class UpdateListingRequest(Request):
201
204
 
202
205
 
203
206
  class UpdateListingInventoryRequest(Request):
204
- nullable: List[str] = []
207
+ nullable: List[str] = ["readiness_state_on_property"]
205
208
  mandatory: List[str] = ["products"]
206
209
 
207
210
  def __init__(
@@ -210,11 +213,13 @@ class UpdateListingInventoryRequest(Request):
210
213
  price_on_property: Optional[List[int]] = None,
211
214
  quantity_on_property: Optional[List[int]] = None,
212
215
  sku_on_property: Optional[List[int]] = None,
216
+ readiness_state_on_property: Optional[List[int]] = None,
213
217
  ):
214
218
  self.products = products
215
219
  self.price_on_property = price_on_property
216
220
  self.quantity_on_property = quantity_on_property
217
221
  self.sku_on_property = sku_on_property
222
+ self.readiness_state_on_property = readiness_state_on_property
218
223
  super().__init__(
219
224
  nullable=UpdateListingInventoryRequest.nullable,
220
225
  mandatory=UpdateListingInventoryRequest.mandatory,
@@ -349,6 +354,21 @@ class UpdateListingTranslationRequest(Request):
349
354
  )
350
355
 
351
356
 
357
+ class UpdateListingPersonalizationRequest(Request):
358
+ nullable: List[str] = []
359
+ mandatory: List[str] = ["personalization_questions"]
360
+
361
+ def __init__(
362
+ self,
363
+ personalization_questions: Optional[List[Dict[str, Any]]] = None,
364
+ ):
365
+ self.personalization_questions = personalization_questions
366
+ super().__init__(
367
+ nullable=UpdateListingPersonalizationRequest.nullable,
368
+ mandatory=UpdateListingPersonalizationRequest.mandatory,
369
+ )
370
+
371
+
352
372
  class UpdateListingVideoRequest(FileRequest):
353
373
  nullable: List[str] = ["file"]
354
374
  mandatory: List[str] = []
@@ -0,0 +1,61 @@
1
+ from typing import List, Optional
2
+
3
+ from etsy_python.v3.enums.ProcessingProfile import ProcessingTimeUnit, ReadinessState
4
+ from etsy_python.v3.models.Request import Request
5
+
6
+
7
+ class CreateShopReadinessStateDefinitionRequest(Request):
8
+ nullable: List[str] = [
9
+ "processing_time_unit",
10
+ ]
11
+ mandatory: List[str] = [
12
+ "readiness_state",
13
+ "min_processing_time",
14
+ "max_processing_time",
15
+ ]
16
+
17
+ def __init__(
18
+ self,
19
+ readiness_state: Optional[ReadinessState] = None,
20
+ min_processing_time: Optional[int] = None,
21
+ max_processing_time: Optional[int] = None,
22
+ processing_time_unit: Optional[ProcessingTimeUnit] = None,
23
+ ):
24
+ self.readiness_state = readiness_state.value if readiness_state else None
25
+ self.min_processing_time = min_processing_time
26
+ self.max_processing_time = max_processing_time
27
+ self.processing_time_unit = (
28
+ processing_time_unit.value if processing_time_unit else None
29
+ )
30
+ super().__init__(
31
+ nullable=CreateShopReadinessStateDefinitionRequest.nullable,
32
+ mandatory=CreateShopReadinessStateDefinitionRequest.mandatory,
33
+ )
34
+
35
+
36
+ class UpdateShopReadinessStateDefinitionRequest(Request):
37
+ nullable: List[str] = [
38
+ "readiness_state",
39
+ "min_processing_time",
40
+ "max_processing_time",
41
+ "processing_time_unit",
42
+ ]
43
+ mandatory: List[str] = []
44
+
45
+ def __init__(
46
+ self,
47
+ readiness_state: Optional[ReadinessState] = None,
48
+ min_processing_time: Optional[int] = None,
49
+ max_processing_time: Optional[int] = None,
50
+ processing_time_unit: Optional[ProcessingTimeUnit] = None,
51
+ ):
52
+ self.readiness_state = readiness_state.value if readiness_state else None
53
+ self.min_processing_time = min_processing_time
54
+ self.max_processing_time = max_processing_time
55
+ self.processing_time_unit = (
56
+ processing_time_unit.value if processing_time_unit else None
57
+ )
58
+ super().__init__(
59
+ nullable=UpdateShopReadinessStateDefinitionRequest.nullable,
60
+ mandatory=UpdateShopReadinessStateDefinitionRequest.mandatory,
61
+ )
@@ -15,6 +15,7 @@ class Request:
15
15
  raise ValueError
16
16
 
17
17
  def check_mandatory(self) -> bool:
18
+ # Keys must match the attribute name (e.g. "_type", not "type").
18
19
  if self._mandatory is not None:
19
20
  for key in self._mandatory:
20
21
  try:
@@ -28,7 +29,7 @@ class Request:
28
29
  return [
29
30
  key
30
31
  for key, value in self.__dict__.items()
31
- if key in self._nullable and (value == [] or value == "" or value == 0)
32
+ if key in self._nullable and (value == [] or value == "" or (value == 0 and not isinstance(value, bool)))
32
33
  ]
33
34
 
34
35
  def get_dict(self) -> Any:
@@ -10,6 +10,8 @@ from etsy_python.v3.models.Request import Request
10
10
 
11
11
  class CreateShopShippingProfileRequest(Request):
12
12
  nullable: List[str] = [
13
+ "min_processing_time",
14
+ "max_processing_time",
13
15
  "destination_country_iso",
14
16
  "mail_class",
15
17
  "min_delivery_days",
@@ -20,8 +22,6 @@ class CreateShopShippingProfileRequest(Request):
20
22
  "origin_country_iso",
21
23
  "primary_cost",
22
24
  "secondary_cost",
23
- "min_processing_time",
24
- "max_processing_time",
25
25
  ]
26
26
 
27
27
  def __init__(
@@ -131,7 +131,8 @@ class CreateShopShippingProfileDestinationRequest(Request):
131
131
  class UpdateShopShippingProfileDestinationRequest(Request):
132
132
  nullable: List[str] = [
133
133
  "primary_cost",
134
- "secondary_cost" "destination_country_iso",
134
+ "secondary_cost",
135
+ "destination_country_iso",
135
136
  "shipping_carrier_id",
136
137
  "mail_class",
137
138
  "min_delivery_days",
@@ -172,7 +173,7 @@ class CreateShopShippingProfileUpgradeRequest(Request):
172
173
  "max_delivery_days",
173
174
  ]
174
175
  mandatory: List[str] = [
175
- "type",
176
+ "_type",
176
177
  "upgrade_name",
177
178
  "price",
178
179
  "secondary_price",
@@ -189,6 +190,8 @@ class CreateShopShippingProfileUpgradeRequest(Request):
189
190
  min_delivery_days: Optional[int] = None,
190
191
  max_delivery_days: Optional[int] = None,
191
192
  ) -> None:
193
+ # Stored as _type to avoid shadowing Python's builtin `type`.
194
+ # todict() maps _type -> "type" for API serialization.
192
195
  self._type = profile_type.value if profile_type else None
193
196
  self.upgrade_name = upgrade_name
194
197
  self.price = price
@@ -209,7 +212,8 @@ class UpdateShopShippingProfileUpgradeRequest(Request):
209
212
  "upgrade_name",
210
213
  "price",
211
214
  "secondary_price",
212
- "shipping_carrier_id" "mail_class",
215
+ "shipping_carrier_id",
216
+ "mail_class",
213
217
  "min_delivery_days",
214
218
  "max_delivery_days",
215
219
  ]
@@ -227,6 +231,8 @@ class UpdateShopShippingProfileUpgradeRequest(Request):
227
231
  max_delivery_days: Optional[int] = None,
228
232
  ) -> None:
229
233
  self.upgrade_name = upgrade_name
234
+ # Stored as _type to avoid shadowing Python's builtin `type`.
235
+ # todict() maps _type -> "type" for API serialization.
230
236
  self._type = profile_type.value if profile_type else None
231
237
  self.price = price
232
238
  self.secondary_price = secondary_price
@@ -20,7 +20,7 @@ class HolidayPreferencesResource:
20
20
  def update_holiday_preferences(
21
21
  self,
22
22
  shop_id: int,
23
- holiday_id: Optional[Union[HOLIDAYS, US_HOLIDAYS, CA_HOLIDAYS, str]],
23
+ holiday_id: Optional[Union[HOLIDAYS, US_HOLIDAYS, CA_HOLIDAYS, int]],
24
24
  holiday_preference: UpdateHolidayPreferencesRequest,
25
25
  ) -> Union[Response, RequestException]:
26
26
  endpoint = f"/shops/{shop_id}/holiday-preferences/{holiday_id}"