From cde957930176d141165386f56011347e5e295d74 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:09:49 +0530 Subject: [PATCH 1/2] Added asset fields support --- CHANGELOG.md | 5 +++ contentstack/__init__.py | 2 +- tests/test_assets.py | 81 +++++++++++++++++++++++++++++++++++----- tests/test_entry.py | 40 ++++++++++++++++++++ 4 files changed, 118 insertions(+), 10 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 11ba6dd..bc7cedd 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -1,5 +1,10 @@ # CHANGELOG +## _v2.5.0_ + +### **Date: 02-March-2026** + +- Assets fields(DAM 2.0) support added ## _v2.4.1_ ### **Date: 10-November-2025** diff --git a/contentstack/__init__.py b/contentstack/__init__.py index 70b2807..fc6f5e0 100644 --- a/contentstack/__init__.py +++ b/contentstack/__init__.py @@ -22,7 +22,7 @@ __title__ = 'contentstack-delivery-python' __author__ = 'contentstack' __status__ = 'debug' -__version__ = 'v2.4.1' +__version__ = 'v2.5.0' __endpoint__ = 'cdn.contentstack.io' __email__ = 'support@contentstack.com' __developer_email__ = 'mobile@contentstack.com' diff --git a/tests/test_assets.py b/tests/test_assets.py index f2ae65c..b494f81 100644 --- a/tests/test_assets.py +++ b/tests/test_assets.py @@ -55,13 +55,13 @@ def test_014_setting_retry_strategy_api(self): def test_01_assets_query_initial_run(self): result = self.asset_query.find() - if result is not None: - assets = result['assets'] - for item in assets: - if item['title'] == 'if_icon-72-lightning_316154_(1).png': - global ASSET_UID - ASSET_UID = item['uid'] - self.assertEqual(8, len(assets)) + self.assertIsNotNone(result) + assets = result['assets'] + for item in assets: + if item['title'] == 'if_icon-72-lightning_316154_(1).png': + global ASSET_UID + ASSET_UID = item['uid'] + self.assertGreaterEqual(len(assets), 8) def test_02_asset_method(self): self.asset = self.stack.asset(uid=ASSET_UID) @@ -117,14 +117,37 @@ def test_08_support_include_fallback(self): self.assertEqual({'environment': 'development', 'include_fallback': 'true'}, asset_params) + def test_08a_asset_fields_single_asset(self): + """Test single asset asset_fields sets asset_params""" + self.asset = self.stack.asset(uid=ASSET_UID or 'test_asset_uid') + self.asset.asset_fields('user_defined_fields', 'visual_markups') + self.assertEqual(['user_defined_fields', 'visual_markups'], + self.asset.asset_params['asset_fields[]']) + + def test_08b_asset_fields_single_asset_chained_calls(self): + """Test single asset asset_fields with chained calls""" + self.asset = self.stack.asset(uid=ASSET_UID or 'test_asset_uid') + self.asset.asset_fields('user_defined_fields').asset_fields('visual_markups') + self.assertEqual(['user_defined_fields', 'visual_markups'], + self.asset.asset_params['asset_fields[]']) + + def test_08c_asset_fields_single_asset_all_supported_values(self): + """Test single asset asset_fields with all supported values""" + self.asset = self.stack.asset(uid=ASSET_UID or 'test_asset_uid') + self.asset.asset_fields('user_defined_fields', 'embedded_metadata', + 'ai_generated_metadata', 'visual_markups') + self.assertEqual( + ['user_defined_fields', 'embedded_metadata', 'ai_generated_metadata', 'visual_markups'], + self.asset.asset_params['asset_fields[]']) + ############################################ # ==== Asset Query ==== ############################################ def test_09_assets_query(self): result = self.asset_query.find() - if result is not None: - self.assertEqual(8, len(result['assets'])) + self.assertIsNotNone(result) + self.assertGreaterEqual(len(result['assets']), 8) def test_10_assets_base_query_where_exclude_title(self): query = self.asset_query.where( @@ -211,6 +234,46 @@ def test_25_include_metadata(self): self.assertTrue( self.asset_query.asset_query_params.__contains__('include_metadata')) + def test_25a_asset_query_asset_fields_single_field(self): + """Test asset_query asset_fields with a single field""" + query = self.asset_query.asset_fields('user_defined_fields') + self.assertEqual(['user_defined_fields'], + query.asset_query_params['asset_fields[]']) + + def test_25b_asset_query_asset_fields_multiple_fields(self): + """Test asset_query asset_fields with multiple fields""" + query = self.asset_query.asset_fields('user_defined_fields', 'visual_markups') + self.assertEqual(['user_defined_fields', 'visual_markups'], + query.asset_query_params['asset_fields[]']) + + def test_25c_asset_query_asset_fields_chained_calls(self): + """Test asset_query asset_fields with chained calls""" + query = (self.asset_query + .asset_fields('user_defined_fields') + .asset_fields('visual_markups')) + self.assertEqual(['user_defined_fields', 'visual_markups'], + query.asset_query_params['asset_fields[]']) + + def test_25d_asset_query_asset_fields_all_supported_values(self): + """Test asset_query asset_fields with all supported values""" + query = (self.asset_query + .asset_fields('user_defined_fields', 'embedded_metadata', + 'ai_generated_metadata', 'visual_markups')) + self.assertEqual( + ['user_defined_fields', 'embedded_metadata', 'ai_generated_metadata', 'visual_markups'], + query.asset_query_params['asset_fields[]']) + + def test_25e_asset_query_asset_fields_with_other_params(self): + """Test asset_query asset_fields combined with include_metadata and locale""" + query = (self.asset_query + .asset_fields('user_defined_fields', 'visual_markups') + .include_metadata() + .locale('en-us')) + self.assertEqual(['user_defined_fields', 'visual_markups'], + query.asset_query_params['asset_fields[]']) + self.assertEqual('true', query.asset_query_params['include_metadata']) + self.assertEqual('en-us', query.asset_query_params['locale']) + def test_26_where_with_include_count_and_pagination(self): """Test combination of where, include_count, skip, and limit for assets""" query = (self.asset_query diff --git a/tests/test_entry.py b/tests/test_entry.py index e2f2462..6e388fc 100644 --- a/tests/test_entry.py +++ b/tests/test_entry.py @@ -363,6 +363,46 @@ def test_46_entry_all_queryable_methods_combined(self): self.assertIn('include_reference_content_type_uid', entry.entry_queryable_param) self.assertEqual('value', entry.entry_queryable_param['custom']) + def test_47_entry_asset_fields_single_field(self): + """Test entry asset_fields with a single field""" + entry = self.stack.content_type('faq').entry(FAQ_UID).asset_fields('user_defined_fields') + self.assertEqual(['user_defined_fields'], entry.entry_queryable_param['asset_fields[]']) + + def test_48_entry_asset_fields_multiple_fields(self): + """Test entry asset_fields with multiple fields in one call""" + entry = (self.stack.content_type('faq') + .entry(FAQ_UID) + .asset_fields('user_defined_fields', 'visual_markups')) + self.assertEqual(['user_defined_fields', 'visual_markups'], + entry.entry_queryable_param['asset_fields[]']) + + def test_49_entry_asset_fields_chained_calls(self): + """Test entry asset_fields with chained calls""" + entry = (self.stack.content_type('faq') + .entry(FAQ_UID) + .asset_fields('user_defined_fields') + .asset_fields('visual_markups')) + self.assertEqual(['user_defined_fields', 'visual_markups'], + entry.entry_queryable_param['asset_fields[]']) + + def test_50_entry_asset_fields_all_supported_values(self): + """Test entry asset_fields with all supported values""" + entry = (self.stack.content_type('faq') + .entry(FAQ_UID) + .asset_fields('user_defined_fields', 'embedded_metadata', + 'ai_generated_metadata', 'visual_markups')) + self.assertEqual( + ['user_defined_fields', 'embedded_metadata', 'ai_generated_metadata', 'visual_markups'], + entry.entry_queryable_param['asset_fields[]']) + + def test_51_query_asset_fields(self): + """Test query asset_fields sets entry_queryable_param""" + query = (self.stack.content_type('faq') + .query() + .asset_fields('user_defined_fields', 'visual_markups')) + self.assertEqual(['user_defined_fields', 'visual_markups'], + query.entry_queryable_param['asset_fields[]']) + if __name__ == '__main__': unittest.main() From 5ee485e05f55c69254a241f3f1a37be722c68065 Mon Sep 17 00:00:00 2001 From: sunil-lakshman <104969541+sunil-lakshman@users.noreply.github.com> Date: Fri, 27 Feb 2026 11:16:46 +0530 Subject: [PATCH 2/2] Added flask version bump --- requirements.txt | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/requirements.txt b/requirements.txt index 0201897..5ac3538 100644 --- a/requirements.txt +++ b/requirements.txt @@ -34,10 +34,10 @@ Babel==2.14.0 pep517==0.13.1 tomli~=2.0.1 werkzeug~=3.1.5 -Flask~=2.3.2 +Flask~=3.1.3 click~=8.1.7 MarkupSafe==2.1.5 -blinker~=1.8.2 +blinker~=1.9.0 itsdangerous~=2.2.0 isort==5.13.2 pkginfo==1.11.1