Skip to content

Commit e8cb6d1

Browse files
OMpawar-21claude
andcommitted
feat(DX-9677): add taxonomy publish/unpublish/localize/unlocalize and term localize/unlocalize
Adds six new methods to the Python management SDK taxonomy/terms surfaces: - Taxonomy.publish() / unpublish() — POST /taxonomies/publish|unpublish (collection-level) - Taxonomy.localize() / unlocalize() — POST|DELETE /taxonomies/{uid}?locale=... - Terms.localize() / unlocalize() — POST|DELETE /taxonomies/{uid}/terms/{uid}?locale=... Unit tests (21 pass) and integration tests included. Locale passed via add_param("locale", "...") following existing SDK convention. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
1 parent d40cb5f commit e8cb6d1

6 files changed

Lines changed: 236 additions & 3 deletions

File tree

contentstack_management/taxonomies/taxonomy.py

Lines changed: 83 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -144,10 +144,92 @@ 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 given environments and locales.
150+
Call on a collection-level instance: stack.taxonomy().publish(...)
151+
:param data: Request body with keys: locales, environments, items, scheduled_at.
152+
153+
-------------------------------
154+
[Example:]
155+
>>> data = {
156+
>>> "locales": ["en-us"],
157+
>>> "environments": ["production"],
158+
>>> "items": [{"uid": "taxonomy_uid"}]
159+
>>> }
160+
>>> import contentstack_management
161+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
162+
>>> result = client.stack('api_key').taxonomy().publish(data).json()
163+
164+
-------------------------------
165+
"""
166+
data = json.dumps(data)
167+
return self.client.post(f"{self.path}/publish", headers=self.client.headers, data=data, params=self.params)
168+
169+
def unpublish(self, data: dict):
170+
"""
171+
Unpublish one or more taxonomies from the given environments and locales.
172+
Call on a collection-level instance: stack.taxonomy().unpublish(...)
173+
:param data: Request body with keys: locales, environments, items, scheduled_at.
174+
175+
-------------------------------
176+
[Example:]
177+
>>> data = {
178+
>>> "locales": ["en-us"],
179+
>>> "environments": ["production"],
180+
>>> "items": [{"uid": "taxonomy_uid"}]
181+
>>> }
182+
>>> import contentstack_management
183+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
184+
>>> result = client.stack('api_key').taxonomy().unpublish(data).json()
185+
186+
-------------------------------
187+
"""
188+
data = json.dumps(data)
189+
return self.client.post(f"{self.path}/unpublish", headers=self.client.headers, data=data, params=self.params)
190+
191+
def localize(self, data: dict):
192+
"""
193+
Localize a taxonomy into the locale specified via add_param("locale", "...").
194+
:param data: Request body, e.g. {"taxonomy": {"name": "Localized name"}}.
195+
196+
-------------------------------
197+
[Example:]
198+
>>> import contentstack_management
199+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
200+
>>> tax = client.stack('api_key').taxonomy('taxonomy_uid')
201+
>>> tax.add_param("locale", "hi-in")
202+
>>> result = tax.localize({"taxonomy": {"name": "Taxonomy HI"}}).json()
203+
204+
-------------------------------
205+
"""
206+
self.validate_taxonomy_uid()
207+
url = f"{self.path}/{self.taxonomy_uid}"
208+
data = json.dumps(data)
209+
return self.client.post(url, headers=self.client.headers, data=data, params=self.params)
210+
211+
def unlocalize(self):
212+
"""
213+
Unlocalize a taxonomy from the locale specified via add_param("locale", "...").
214+
215+
-------------------------------
216+
[Example:]
217+
>>> import contentstack_management
218+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
219+
>>> tax = client.stack('api_key').taxonomy('taxonomy_uid')
220+
>>> tax.add_param("locale", "hi-in")
221+
>>> result = tax.unlocalize().json()
222+
223+
-------------------------------
224+
"""
225+
self.validate_taxonomy_uid()
226+
url = f"{self.path}/{self.taxonomy_uid}"
227+
return self.client.delete(url, headers=self.client.headers, params=self.params)
228+
147229
def validate_taxonomy_uid(self):
148230
if self.taxonomy_uid is None or '':
149231
raise ArgumentException(TAXONOMY_UID_REQUIRED)
150-
232+
151233
def terms(self, terms_uid: str = None):
152234
self.validate_taxonomy_uid()
153235
return Terms(self.client, self.taxonomy_uid, terms_uid)

contentstack_management/terms/terms.py

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -282,14 +282,54 @@ 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):
286+
"""
287+
Localize a term into the locale specified via add_param("locale", "...").
288+
:param data: Request body, e.g. {"term": {"uid": "...", "name": "..."}}.
289+
290+
-------------------------------
291+
[Example:]
292+
>>> import contentstack_management
293+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
294+
>>> term = client.stack('api_key').taxonomy('taxonomy_uid').terms('term_uid')
295+
>>> term.add_param("locale", "hi-in")
296+
>>> result = term.localize({"term": {"uid": "term_uid", "name": "Term HI"}}).json()
297+
298+
-------------------------------
299+
"""
300+
self.validate_taxonomy_uid()
301+
self.validate_terms_uid()
302+
url = f"{self.path}/{self.terms_uid}"
303+
data = json.dumps(data)
304+
return self.client.post(url, headers=self.client.headers, data=data, params=self.params)
305+
306+
def unlocalize(self):
307+
"""
308+
Unlocalize a term from the locale specified via add_param("locale", "...").
309+
310+
-------------------------------
311+
[Example:]
312+
>>> import contentstack_management
313+
>>> client = contentstack_management.Client(authtoken='your_authtoken')
314+
>>> term = client.stack('api_key').taxonomy('taxonomy_uid').terms('term_uid')
315+
>>> term.add_param("locale", "hi-in")
316+
>>> result = term.unlocalize().json()
317+
318+
-------------------------------
319+
"""
320+
self.validate_taxonomy_uid()
321+
self.validate_terms_uid()
322+
url = f"{self.path}/{self.terms_uid}"
323+
return self.client.delete(url, headers=self.client.headers, params=self.params)
324+
285325
def validate_taxonomy_uid(self):
286326
if self.taxonomy_uid is None or '':
287327
raise ArgumentException(TAXONOMY_UID_REQUIRED)
288-
328+
289329
def validate_terms_uid(self):
290330
if self.terms_uid is None or '':
291331
raise ArgumentException(TERMS_UID_REQUIRED)
292-
332+
293333
def validate_term_string(self, term_string):
294334
if term_string is None or '':
295335
raise ArgumentException(TERM_STRING_REQUIRED)

tests/integration/api/test_07_taxonomy.py

Lines changed: 39 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,45 @@ def test_fetch_nonexistent(self, stack):
3939
h.assert_status(resp, 404, 422)
4040

4141

42+
class TestTaxonomyPublish:
43+
def test_publish(self, stack, store):
44+
uid = store["taxonomies"]["main"]
45+
data = {
46+
"locales": ["en-us"],
47+
"environments": ["development"],
48+
"items": [{"uid": uid}]
49+
}
50+
resp = stack.taxonomy().publish(data)
51+
h.assert_status(resp, 200, 202)
52+
53+
def test_unpublish(self, stack, store):
54+
uid = store["taxonomies"]["main"]
55+
data = {
56+
"locales": ["en-us"],
57+
"environments": ["development"],
58+
"items": [{"uid": uid}]
59+
}
60+
resp = stack.taxonomy().unpublish(data)
61+
h.assert_status(resp, 200, 202)
62+
63+
64+
class TestTaxonomyLocalize:
65+
def test_localize(self, stack, store):
66+
uid = store["taxonomies"]["main"]
67+
tax = stack.taxonomy(uid)
68+
tax.add_param("locale", "hi-in")
69+
resp = tax.localize({"taxonomy": {"name": f"Localized {uid}"}})
70+
h.assert_status(resp, 200, 201)
71+
72+
def test_unlocalize(self, stack, store):
73+
uid = store["taxonomies"]["main"]
74+
tax = stack.taxonomy(uid)
75+
tax.add_param("locale", "hi-in")
76+
stack.client.headers.pop("Content-Type", None)
77+
resp = tax.unlocalize()
78+
h.assert_status(resp, 200, 204)
79+
80+
4281
class TestTaxonomyDelete:
4382
def test_delete(self, stack):
4483
uid = h.generate_valid_uid("tax_del")

tests/integration/api/test_08_terms.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,6 +78,23 @@ def test_fetch_nonexistent(self, stack, taxonomy_uid):
7878
h.assert_status(resp, 404, 422)
7979

8080

81+
class TestTermsLocalize:
82+
def test_localize(self, stack, store, taxonomy_uid):
83+
uid = store["terms"]["main"]
84+
term = stack.taxonomy(taxonomy_uid).terms(uid)
85+
term.add_param("locale", "hi-in")
86+
resp = term.localize({"term": {"uid": uid, "name": f"Localized {uid}"}})
87+
h.assert_status(resp, 200, 201)
88+
89+
def test_unlocalize(self, stack, store, taxonomy_uid):
90+
uid = store["terms"]["main"]
91+
term = stack.taxonomy(taxonomy_uid).terms(uid)
92+
term.add_param("locale", "hi-in")
93+
stack.client.headers.pop("Content-Type", None)
94+
resp = term.unlocalize()
95+
h.assert_status(resp, 200, 204)
96+
97+
8198
class TestTermsDelete:
8299
def test_delete(self, stack, taxonomy_uid):
83100
uid = h.generate_valid_uid("term_del")

tests/unit/taxonomies/test_taxonomy_unit.py

Lines changed: 38 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -71,3 +71,41 @@ 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_taxonomy(self):
76+
data = {
77+
"locales": ["en-us"],
78+
"environments": ["production"],
79+
"items": [{"uid": taxonomy_uid}]
80+
}
81+
response = self.client.stack(api_key).taxonomy().publish(data)
82+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/publish")
83+
self.assertEqual(response.request.method, "POST")
84+
self.assertEqual(response.request.headers["Content-Type"], "application/json")
85+
86+
def test_unpublish_taxonomy(self):
87+
data = {
88+
"locales": ["en-us"],
89+
"environments": ["production"],
90+
"items": [{"uid": taxonomy_uid}]
91+
}
92+
response = self.client.stack(api_key).taxonomy().unpublish(data)
93+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/unpublish")
94+
self.assertEqual(response.request.method, "POST")
95+
self.assertEqual(response.request.headers["Content-Type"], "application/json")
96+
97+
def test_localize_taxonomy(self):
98+
data = {"taxonomy": {"name": "Taxonomy HI"}}
99+
tax = self.client.stack(api_key).taxonomy(taxonomy_uid)
100+
tax.add_param("locale", "hi-in")
101+
response = tax.localize(data)
102+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/{taxonomy_uid}?locale=hi-in")
103+
self.assertEqual(response.request.method, "POST")
104+
self.assertEqual(response.request.headers["Content-Type"], "application/json")
105+
106+
def test_unlocalize_taxonomy(self):
107+
tax = self.client.stack(api_key).taxonomy(taxonomy_uid)
108+
tax.add_param("locale", "hi-in")
109+
response = tax.unlocalize()
110+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/{taxonomy_uid}?locale=hi-in")
111+
self.assertEqual(response.request.method, "DELETE")

tests/unit/terms/test_terms_unit.py

Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -95,5 +95,22 @@ 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_term(self):
99+
data = {"term": {"uid": terms_uid, "name": "Term HI"}}
100+
term = self.client.stack(api_key).taxonomy(taxonomy_uid).terms(terms_uid)
101+
term.add_param("locale", "hi-in")
102+
response = term.localize(data)
103+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/{taxonomy_uid}/terms/{terms_uid}?locale=hi-in")
104+
self.assertEqual(response.request.method, "POST")
105+
self.assertEqual(response.request.headers["Content-Type"], "application/json")
106+
107+
def test_unlocalize_term(self):
108+
term = self.client.stack(api_key).taxonomy(taxonomy_uid).terms(terms_uid)
109+
term.add_param("locale", "hi-in")
110+
response = term.unlocalize()
111+
self.assertEqual(response.request.url, f"{self.client.endpoint}taxonomies/{taxonomy_uid}/terms/{terms_uid}?locale=hi-in")
112+
self.assertEqual(response.request.method, "DELETE")
113+
self.assertEqual(response.request.headers["Content-Type"], "application/json")
114+
98115
if __name__ == '__main__':
99116
unittest.main()

0 commit comments

Comments
 (0)