Repository navigation
feat: sync SDK with Etsy API spec (Nov 2026 GPSR economic operators) - #50
Merged
Merged
Conversation
- Add ShopEconomicOperatorResource: create, list, get, and update (PATCH) GPSR economic operator records, with request models. - Add the six gpsr_* fields to CreateDraftListingRequest and UpdateListingRequest, plus a GPSROperatorType enum. All are nullable, so "" or 0 sends null to clear a value. - Deprecate get_listing_offering: Etsy removed getListingOffering. It now emits a DeprecationWarning and has an audit-ignore entry. - Update specs/baseline.json to the 2026-11-10 spec. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Add a CLEAR sentinel for sending null on nullable fields, and share one is_null_value rule between Request.get_nulled and todict. Request rejects CLEAR on a non-nullable field. "", [] and 0 still clear. - Type the GPSR listing fields and the nullable economic operator fields to accept CLEAR. - Assign the GPSR and economic operator fields by name through Request._assign_fields, so a misordered argument fails instead of landing in the wrong field. - Reject blank required economic operator fields locally, which Etsy would reject with a 400. - Warn when ListingOfferingResource is constructed, not only when get_listing_offering is called. - Give the listing model tests a module-level create helper. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Keep CLEAR a singleton across copy, deepcopy and pickle, and serialize
any Clear as null in todict, so a copied request no longer sends {}.
- Re-check for CLEAR on non-nullable fields in get_dict, so a field set
to CLEAR after construction raises instead of sending {}.
- Reject blank or cleared fields on createShopEconomicOperator. A new
record has nothing to clear.
- Reject GPSR type/id pairs Etsy rejects: an id without type
economic_operator, and type economic_operator without an id on create.
- Test that the create mandatory list matches NON_BLANK_FIELDS.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- Send "type": null, not "_type": null, when the listing type is cleared. todict now nulls exactly the keys get_nulled selected, with no second null check. - Add Request.validate(), run on construction and in get_dict, so checks also catch fields reassigned after construction. The GPSR type/id check and the economic operator checks now live there. - Move the GPSR fields back into a _GPSRFieldsMixin, and require an id whenever type economic_operator is sent, on update too. - Economic operator requests reject any blank or whitespace-only string (clear with CLEAR), and an update with no fields. - Name the field without its storage underscore in the CLEAR error, and correct the CLEAR docs about type hints. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
- On update, a GPSR type of economic_operator without an id is no longer rejected locally. The listing may already store the id, so Etsy decides. Create still requires the id. - Rename Request.validate() to _validate(), so it cannot collide with a validate method on a user's own Request subclass. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Contributor
Test Coverage ReportOverall: 100% (1889/1889 statements covered) Coverage by file
Updated by PR Tests |
- todict nulls a nullable key only when its value is a null value again. External callers that pass a model's full nullable list no longer wipe real values. The "_type" to "type" key fix stays. - Reject type economic_operator sent with a cleared id (CLEAR or 0), on create and update. Etsy always rejects that pair. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Etsy's 2026-11-10 spec adds GPSR (EU General Product Safety Regulation) support and removes one endpoint. The SDK now covers all 107 operations again (it was at 96.3%).
The audit found 1 Must Fix and 2 Should Fix items:
getListingOffering.ListingOfferingResourceandget_listing_offeringstay so existing callers don't break, but both emit aDeprecationWarning. The method has anextra_methodentry inspecs/audit-ignore.json.ShopEconomicOperatorResourcecovers create, list, get, and update (PATCH) for economic operators. Etsy has no delete endpoint for them.CreateDraftListingRequestandUpdateListingRequestaccept the six newgpsr_*fields, with aGPSROperatorTypeenum (seller,economic_operator).Three code review rounds added these changes:
CLEARsentinel (etsy_python.v3.common.Utils.CLEAR) sendsnullfor any nullable field."",[]and0still clear values as before.CLEARsurvives copy, deepcopy, and pickle. ACLEARon a non-nullable field raisesValueError.Request._validate()runs on construction and again inget_dict(). It checksCLEARplacement, GPSR type/id pairs, and blank economic operator fields.listing_typesent"_type": null. It now sends"type": null.Informational:
check_releases.pyhit GitHub's rate limit, and the script can't take a token.gh apishows no Etsy releases since 2026-03-24.Merge note: squash-merge with this title. The publish workflow reads the head commit subject, so
feat:gives a minor bump.Test plan
pytest: 561 passedpython scripts/audit_sdk.py --spec specs/latest.json: 100% coverage, no drift, no stale ignorespython scripts/check_version_consistency.pycreate_shop_economic_operatorand a GPSR listing update against a real EU shop🤖 Generated with Claude Code