Skip to content

Commit 88d5b02

Browse files
OMpawar-21claude
andcommitted
feat: add taxonomy publish/unpublish/localize/unlocalize and terms localize/unlocalize
Closes parity gap with JS SDK and Java (feat/DX-9676-taxonomy-publish). Taxonomy (taxonomy.py): - publish(data) → POST /taxonomies/publish (collection-level) - unpublish(data) → POST /taxonomies/unpublish (collection-level) - localize(data, locale) → POST /taxonomies/{uid}?locale= (instance-level) - unlocalize(locale) → DELETE /taxonomies/{uid}?locale= (instance-level) Terms (terms.py): - localize(data, locale) → POST /taxonomies/{t}/terms/{uid}?locale= (instance-level) - unlocalize(locale) → DELETE /taxonomies/{t}/terms/{uid}?locale= (instance-level) 21/21 unit tests pass. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d40cb5f commit 88d5b02

4 files changed

Lines changed: 139 additions & 3 deletions

File tree

contentstack_management/taxonomies/taxonomy.py

Lines changed: 64 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,73 @@ def delete(self, taxonomy_uid: str = None):
144144
return self.client.delete(url, headers = self.client.headers, params = self.params)
145145

146146

147+
def publish(self, data: dict):
148+
"""
149+
Publish one or more taxonomies to the specified environments and locales.
150+
Call on a collection-level instance (no taxonomy_uid set).
151+
152+
:param data: ``{"locales": [...], "environments": [...], "items": [{"uid": "..."}]}``
153+
:return: requests.Response
154+
155+
[Example:]
156+
>>> data = {"locales": ["en-us"], "environments": ["production"], "items": [{"uid": "taxonomy_1"}]}
157+
>>> client.stack('api_key').taxonomy().publish(data).json()
158+
"""
159+
url = f"{self.path}/publish"
160+
return self.client.post(url, headers=self.client.headers, data=json.dumps(data), params=self.params)
161+
162+
def unpublish(self, data: dict):
163+
"""
164+
Unpublish one or more taxonomies from the specified environments and locales.
165+
Call on a collection-level instance (no taxonomy_uid set).
166+
167+
:param data: ``{"locales": [...], "environments": [...], "items": [{"uid": "..."}]}``
168+
:return: requests.Response
169+
170+
[Example:]
171+
>>> data = {"locales": ["en-us"], "environments": ["production"], "items": [{"uid": "taxonomy_1"}]}
172+
>>> client.stack('api_key').taxonomy().unpublish(data).json()
173+
"""
174+
url = f"{self.path}/unpublish"
175+
return self.client.post(url, headers=self.client.headers, data=json.dumps(data), params=self.params)
176+
177+
def localize(self, data: dict, locale: str):
178+
"""
179+
Localize a taxonomy into the specified locale.
180+
Requires a taxonomy_uid (instance-level).
181+
182+
:param data: ``{"taxonomy": {"name": "..."}}``
183+
:param locale: Target locale code, e.g. ``"hi-in"``
184+
:return: requests.Response
185+
186+
[Example:]
187+
>>> client.stack('api_key').taxonomy('uid').localize({"taxonomy": {"name": "Hindi"}}, 'hi-in').json()
188+
"""
189+
self.validate_taxonomy_uid()
190+
self.add_param('locale', locale)
191+
url = f"{self.path}/{self.taxonomy_uid}"
192+
return self.client.post(url, headers=self.client.headers, data=json.dumps(data), params=self.params)
193+
194+
def unlocalize(self, locale: str):
195+
"""
196+
Remove a locale variant of a taxonomy.
197+
Requires a taxonomy_uid (instance-level).
198+
199+
:param locale: Locale code to remove, e.g. ``"hi-in"``
200+
:return: requests.Response
201+
202+
[Example:]
203+
>>> client.stack('api_key').taxonomy('uid').unlocalize('hi-in').json()
204+
"""
205+
self.validate_taxonomy_uid()
206+
self.add_param('locale', locale)
207+
url = f"{self.path}/{self.taxonomy_uid}"
208+
return self.client.delete(url, headers=self.client.headers, params=self.params)
209+
147210
def validate_taxonomy_uid(self):
148211
if self.taxonomy_uid is None or '':
149212
raise ArgumentException(TAXONOMY_UID_REQUIRED)
150-
213+
151214
def terms(self, terms_uid: str = None):
152215
self.validate_taxonomy_uid()
153216
return Terms(self.client, self.taxonomy_uid, terms_uid)

contentstack_management/terms/terms.py

Lines changed: 37 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,49 @@ def descendants(self, terms_uid: str = None):
282282
url = f"{self.path}/{self.terms_uid}/descendants"
283283
return self.client.get(url, headers = self.client.headers, params = self.params)
284284

285+
def localize(self, data: dict, locale: str):
286+
"""
287+
Localize a term into the specified locale.
288+
Requires both taxonomy_uid and terms_uid (instance-level).
289+
290+
:param data: ``{"term": {"name": "..."}}``
291+
:param locale: Target locale code, e.g. ``"hi-in"``
292+
:return: requests.Response
293+
294+
[Example:]
295+
>>> client.stack('api_key').taxonomy('t_uid').terms('term_uid').localize({"term": {"name": "Hindi"}}, 'hi-in').json()
296+
"""
297+
self.validate_taxonomy_uid()
298+
self.validate_terms_uid()
299+
self.add_param('locale', locale)
300+
url = f"{self.path}/{self.terms_uid}"
301+
return self.client.post(url, headers=self.client.headers, data=json.dumps(data), params=self.params)
302+
303+
def unlocalize(self, locale: str):
304+
"""
305+
Remove a locale variant of a term.
306+
Requires both taxonomy_uid and terms_uid (instance-level).
307+
308+
:param locale: Locale code to remove, e.g. ``"hi-in"``
309+
:return: requests.Response
310+
311+
[Example:]
312+
>>> client.stack('api_key').taxonomy('t_uid').terms('term_uid').unlocalize('hi-in').json()
313+
"""
314+
self.validate_taxonomy_uid()
315+
self.validate_terms_uid()
316+
self.add_param('locale', locale)
317+
url = f"{self.path}/{self.terms_uid}"
318+
return self.client.delete(url, headers=self.client.headers, params=self.params)
319+
285320
def validate_taxonomy_uid(self):
286321
if self.taxonomy_uid is None or '':
287322
raise ArgumentException(TAXONOMY_UID_REQUIRED)
288-
323+
289324
def validate_terms_uid(self):
290325
if self.terms_uid is None or '':
291326
raise ArgumentException(TERMS_UID_REQUIRED)
292-
327+
293328
def validate_term_string(self, term_string):
294329
if term_string is None or '':
295330
raise ArgumentException(TERM_STRING_REQUIRED)

tests/unit/taxonomies/test_taxonomy_unit.py

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,28 @@ def test_delete_taxonomy(self):
7171
response = self.client.stack(api_key).taxonomy(taxonomy_uid).delete()
7272
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/{taxonomy_uid}")
7373
self.assertEqual(response.request.method, "DELETE")
74+
75+
def test_publish(self):
76+
data = {"locales": ["en-us"], "environments": ["production"], "items": [{"uid": taxonomy_uid}]}
77+
response = self.client.stack(api_key).taxonomy().publish(data)
78+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/publish")
79+
self.assertEqual(response.request.method, "POST")
80+
81+
def test_unpublish(self):
82+
data = {"locales": ["en-us"], "environments": ["production"], "items": [{"uid": taxonomy_uid}]}
83+
response = self.client.stack(api_key).taxonomy().unpublish(data)
84+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/unpublish")
85+
self.assertEqual(response.request.method, "POST")
86+
87+
def test_localize(self):
88+
data = {"taxonomy": {"name": "Taxonomy Hindi"}}
89+
response = self.client.stack(api_key).taxonomy(taxonomy_uid).localize(data, "hi-in")
90+
self.assertIn(f"taxonomies/{taxonomy_uid}", response.request.url)
91+
self.assertIn("locale=hi-in", response.request.url)
92+
self.assertEqual(response.request.method, "POST")
93+
94+
def test_unlocalize(self):
95+
response = self.client.stack(api_key).taxonomy(taxonomy_uid).unlocalize("hi-in")
96+
self.assertIn(f"taxonomies/{taxonomy_uid}", response.request.url)
97+
self.assertIn("locale=hi-in", response.request.url)
98+
self.assertEqual(response.request.method, "DELETE")

tests/unit/terms/test_terms_unit.py

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,18 @@ def test_descendants(self):
9595
self.assertEqual(response.request.method, "GET")
9696
self.assertEqual(response.request.headers["Content-Type"], "application/json")
9797

98+
def test_localize(self):
99+
data = {"term": {"name": "Term Hindi"}}
100+
response = self.client.stack(api_key).taxonomy(taxonomy_uid).terms(terms_uid).localize(data, "hi-in")
101+
self.assertIn(f"taxonomies/{taxonomy_uid}/terms/{terms_uid}", response.request.url)
102+
self.assertIn("locale=hi-in", response.request.url)
103+
self.assertEqual(response.request.method, "POST")
104+
105+
def test_unlocalize(self):
106+
response = self.client.stack(api_key).taxonomy(taxonomy_uid).terms(terms_uid).unlocalize("hi-in")
107+
self.assertIn(f"taxonomies/{taxonomy_uid}/terms/{terms_uid}", response.request.url)
108+
self.assertIn("locale=hi-in", response.request.url)
109+
self.assertEqual(response.request.method, "DELETE")
110+
98111
if __name__ == '__main__':
99112
unittest.main()

0 commit comments

Comments
 (0)