From 09d2507be4dcc47b129aa78275d3ae531cd19ca8 Mon Sep 17 00:00:00 2001 From: Fabrizio Leoni Date: Mon, 15 Sep 2025 12:15:45 +0200 Subject: [PATCH 1/2] fix(Search: regenerated services with latest API definition Signed-off-by: Fabrizio Leoni --- ibm_platform_services/global_search_v2.py | 101 ++++++++++------------ test/unit/test_global_search_v2.py | 28 +++--- 2 files changed, 57 insertions(+), 72 deletions(-) diff --git a/ibm_platform_services/global_search_v2.py b/ibm_platform_services/global_search_v2.py index d18a57e3..092cdfdb 100644 --- a/ibm_platform_services/global_search_v2.py +++ b/ibm_platform_services/global_search_v2.py @@ -1,6 +1,6 @@ # coding: utf-8 -# (C) Copyright IBM Corp. 2024. +# (C) Copyright IBM Corp. 2025. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -14,7 +14,7 @@ # See the License for the specific language governing permissions and # limitations under the License. -# IBM OpenAPI SDK Code Generator Version: 3.87.0-91c7c775-20240320-213027 +# IBM OpenAPI SDK Code Generator Version: 3.100.0-2ad7a784-20250212-162551 """ Search for resources with the global and shared resource properties repository that is @@ -61,7 +61,9 @@ def new_instance( parameters and external configuration. """ authenticator = get_authenticator_from_environment(service_name) - service = cls(authenticator) + service = cls( + authenticator + ) service.configure_service(service_name) return service @@ -96,7 +98,6 @@ def search( sort: Optional[List[str]] = None, is_deleted: Optional[str] = None, is_reclaimed: Optional[str] = None, - is_public: Optional[str] = None, impersonate_user: Optional[str] = None, can_tag: Optional[str] = None, is_project_resource: Optional[str] = None, @@ -106,21 +107,17 @@ def search( Find instances of resources (v3). Find IAM-enabled resources or storage and network resources that run on classic - infrastructure in a specific account ID. You can apply query strings if necessary. - To filter results, you can insert a string by using the Lucene syntax and the - query string is parsed into a series of terms and operators. A term can be a - single word or a phrase, in which case the search is performed for all the words, - in the same order. To filter for a specific value regardless of the property that - contains it, type the search term without specifying a field. Only resources that - belong to the account ID and that are accessible by the client are returned. + infrastructure in a specific account ID. You must use `/v3/resources/search` when you need to fetch more than `10000` resource items. On the first call, the operation returns a live cursor on the data that you must use on all the subsequent calls to get the next batch of results until you get the empty result set. - By default, the fields that are returned for every resource are `crn`, `name`, - `family`, `type`, and `account_id`. You can specify the subset of the fields you - want in your request using the `fields` request body attribute. Set `"fields": - ["*"]` to discover the set of fields which are available to request. + To filter results, you can apply query strings following the *Lucene* query + syntax. + By default, the fields that are returned for every resource are **crn**, **name**, + **family**, **type**, and **account_id**. You can specify the subset of the fields + you want in your request using the `fields` request body attribute. Set `"fields": + ["*"]` to discover the complete set of fields which are available to request. :param str query: (optional) The Lucene-formatted query string. Default to '*' if not set. @@ -131,8 +128,10 @@ def search( request. :param str search_cursor: (optional) An opaque cursor that is returned on each call and that must be set on the subsequent call to get the next batch - of items. If the search returns no items, then the search_cursor is not - present in the response. + of items. You can stop paging when the search returns less items than the + specified `limit` or when the `search_cursor` is not present in the + response. NOTE: when setting this parameter, any other properties present + in the body will be ignored. :param str x_request_id: (optional) An alphanumeric string that is used to trace the request. The value may include ASCII alphanumerics and any of following segment separators: space ( ), comma (,), hyphen, (-), and @@ -169,10 +168,6 @@ def search( (default), true or any. If false, only not reclaimed documents are returned; if true, only reclaimed documents are returned; If any, both reclaimed and not reclaimed documents are returned. - :param str is_public: (optional) Determines if public resources should be - included in result set or not. Possible values are false (default), true or - any. If false, do not search public resources; if true, search only public - resources; If any, search also public resources. :param str impersonate_user: (optional) The user on whose behalf the search must be performed. Only a GhoST admin can impersonate a user, so be sure you set a GhoST admin IAM token in the Authorization header if you set this @@ -212,7 +207,6 @@ def search( 'sort': convert_list(sort), 'is_deleted': is_deleted, 'is_reclaimed': is_reclaimed, - 'is_public': is_public, 'impersonate_user': impersonate_user, 'can_tag': can_tag, 'is_project_resource': is_project_resource, @@ -261,7 +255,6 @@ class IsDeleted(str, Enum): TRUE = 'true' FALSE = 'false' ANY = 'any' - class IsReclaimed(str, Enum): """ Determines if reclaimed documents should be included in result set or not. @@ -273,18 +266,6 @@ class IsReclaimed(str, Enum): TRUE = 'true' FALSE = 'false' ANY = 'any' - - class IsPublic(str, Enum): - """ - Determines if public resources should be included in result set or not. Possible - values are false (default), true or any. If false, do not search public resources; - if true, search only public resources; If any, search also public resources. - """ - - TRUE = 'true' - FALSE = 'false' - ANY = 'any' - class CanTag(str, Enum): """ Determines if the result set must return the resources that the user can tag or @@ -296,7 +277,6 @@ class CanTag(str, Enum): TRUE = 'true' FALSE = 'false' - class IsProjectResource(str, Enum): """ Determines if documents belonging to Project family should be included in result @@ -322,6 +302,8 @@ class ResultItem: other properties that depend on the resource type. :param str crn: Resource identifier in CRN format. + + This type supports additional properties of type object. """ # The set of defined properties for the class @@ -330,17 +312,22 @@ class ResultItem: def __init__( self, crn: str, - **kwargs, + **kwargs: Optional[object], ) -> None: """ Initialize a ResultItem object. :param str crn: Resource identifier in CRN format. - :param **kwargs: (optional) Any additional properties. + :param object **kwargs: (optional) Additional properties of type object """ self.crn = crn - for _key, _value in kwargs.items(): - setattr(self, _key, _value) + for k, v in kwargs.items(): + if k not in ResultItem._properties: + if not isinstance(v, object): + raise ValueError('Value for additional property {} must be of type object'.format(k)) + setattr(self, k, v) + else: + raise ValueError('Property {} cannot be specified as an additional property'.format(k)) @classmethod def from_dict(cls, _dict: Dict) -> 'ResultItem': @@ -350,7 +337,11 @@ def from_dict(cls, _dict: Dict) -> 'ResultItem': args['crn'] = crn else: raise ValueError('Required property \'crn\' not present in ResultItem JSON') - args.update({k: v for (k, v) in _dict.items() if k not in cls._properties}) + for k, v in _dict.items(): + if k not in cls._properties: + if not isinstance(v, object): + raise ValueError('Value for additional property {} must be of type object'.format(k)) + args[k] = v return cls(**args) @classmethod @@ -363,8 +354,8 @@ def to_dict(self) -> Dict: _dict = {} if hasattr(self, 'crn') and self.crn is not None: _dict['crn'] = self.crn - for _key in [k for k in vars(self).keys() if k not in ResultItem._properties]: - _dict[_key] = getattr(self, _key) + for k in [_k for _k in vars(self).keys() if _k not in ResultItem._properties]: + _dict[k] = getattr(self, k) return _dict def _to_dict(self): @@ -372,21 +363,23 @@ def _to_dict(self): return self.to_dict() def get_properties(self) -> Dict: - """Return a dictionary of arbitrary properties from this instance of ResultItem""" + """Return the additional properties from this instance of ResultItem in the form of a dict.""" _dict = {} - - for _key in [k for k in vars(self).keys() if k not in ResultItem._properties]: - _dict[_key] = getattr(self, _key) + for k in [_k for _k in vars(self).keys() if _k not in ResultItem._properties]: + _dict[k] = getattr(self, k) return _dict def set_properties(self, _dict: dict): - """Set a dictionary of arbitrary properties to this instance of ResultItem""" - for _key in [k for k in vars(self).keys() if k not in ResultItem._properties]: - delattr(self, _key) - - for _key, _value in _dict.items(): - if _key not in ResultItem._properties: - setattr(self, _key, _value) + """Set a dictionary of additional properties in this instance of ResultItem""" + for k in [_k for _k in vars(self).keys() if _k not in ResultItem._properties]: + delattr(self, k) + for k, v in _dict.items(): + if k not in ResultItem._properties: + if not isinstance(v, object): + raise ValueError('Value for additional property {} must be of type object'.format(k)) + setattr(self, k, v) + else: + raise ValueError('Property {} cannot be specified as an additional property'.format(k)) def __str__(self) -> str: """Return a `str` version of this ResultItem object.""" diff --git a/test/unit/test_global_search_v2.py b/test/unit/test_global_search_v2.py index 8afa4a3c..4b45bc75 100644 --- a/test/unit/test_global_search_v2.py +++ b/test/unit/test_global_search_v2.py @@ -1,5 +1,5 @@ # -*- coding: utf-8 -*- -# (C) Copyright IBM Corp. 2024. +# (C) Copyright IBM Corp. 2025. # # Licensed under the Apache License, Version 2.0 (the "License"); # you may not use this file except in compliance with the License. @@ -29,7 +29,9 @@ from ibm_platform_services.global_search_v2 import * -_service = GlobalSearchV2(authenticator=NoAuthAuthenticator()) +_service = GlobalSearchV2( + authenticator=NoAuthAuthenticator() +) _base_url = 'https://api.global-search-tagging.cloud.ibm.com' _service.set_service_url(_base_url) @@ -42,15 +44,8 @@ def preprocess_url(operation_path: str): The returned request URL is used to register the mock response so it needs to match the request URL that is formed by the requests library. """ - # First, unquote the path since it might have some quoted/escaped characters in it - # due to how the generator inserts the operation paths into the unit test code. - operation_path = urllib.parse.unquote(operation_path) - # Next, quote the path using urllib so that we approximate what will - # happen during request processing. - operation_path = urllib.parse.quote(operation_path, safe='/') - - # Finally, form the request URL from the base URL and operation path. + # Form the request URL from the base URL and operation path. request_url = _base_url + operation_path # If the request url does NOT end with a /, then just return it as-is. @@ -116,7 +111,7 @@ def test_search_all_params(self): ) # Set up parameter values - query = 'testString' + query = '*' fields = ['testString'] search_cursor = 'testString' x_request_id = 'testString' @@ -127,7 +122,6 @@ def test_search_all_params(self): sort = ['testString'] is_deleted = 'false' is_reclaimed = 'false' - is_public = 'false' impersonate_user = 'testString' can_tag = 'false' is_project_resource = 'false' @@ -145,7 +139,6 @@ def test_search_all_params(self): sort=sort, is_deleted=is_deleted, is_reclaimed=is_reclaimed, - is_public=is_public, impersonate_user=impersonate_user, can_tag=can_tag, is_project_resource=is_project_resource, @@ -164,13 +157,12 @@ def test_search_all_params(self): assert 'sort={}'.format(','.join(sort)) in query_string assert 'is_deleted={}'.format(is_deleted) in query_string assert 'is_reclaimed={}'.format(is_reclaimed) in query_string - assert 'is_public={}'.format(is_public) in query_string assert 'impersonate_user={}'.format(impersonate_user) in query_string assert 'can_tag={}'.format(can_tag) in query_string assert 'is_project_resource={}'.format(is_project_resource) in query_string # Validate body params req_body = json.loads(str(responses.calls[0].request.body, 'utf-8')) - assert req_body['query'] == 'testString' + assert req_body['query'] == '*' assert req_body['fields'] == ['testString'] assert req_body['search_cursor'] == 'testString' @@ -200,7 +192,7 @@ def test_search_required_params(self): ) # Set up parameter values - query = 'testString' + query = '*' fields = ['testString'] search_cursor = 'testString' @@ -217,7 +209,7 @@ def test_search_required_params(self): assert response.status_code == 200 # Validate body params req_body = json.loads(str(responses.calls[0].request.body, 'utf-8')) - assert req_body['query'] == 'testString' + assert req_body['query'] == '*' assert req_body['fields'] == ['testString'] assert req_body['search_cursor'] == 'testString' @@ -281,7 +273,7 @@ def test_result_item_serialization(self): expected_dict = {'foo': 'testString'} result_item_model.set_properties(expected_dict) actual_dict = result_item_model.get_properties() - assert actual_dict == expected_dict + assert actual_dict.keys() == expected_dict.keys() class TestModel_ScanResult: From c8af733195350d99f512f851c10e0e114c1889f5 Mon Sep 17 00:00:00 2001 From: Fabrizio Leoni Date: Mon, 15 Sep 2025 12:44:52 +0200 Subject: [PATCH 2/2] fix(Search: regenerated services with latest API definition Signed-off-by: Fabrizio Leoni --- ibm_platform_services/global_search_v2.py | 13 +++++++------ test/unit/test_global_search_v2.py | 4 +--- 2 files changed, 8 insertions(+), 9 deletions(-) diff --git a/ibm_platform_services/global_search_v2.py b/ibm_platform_services/global_search_v2.py index 092cdfdb..793c310f 100644 --- a/ibm_platform_services/global_search_v2.py +++ b/ibm_platform_services/global_search_v2.py @@ -61,9 +61,7 @@ def new_instance( parameters and external configuration. """ authenticator = get_authenticator_from_environment(service_name) - service = cls( - authenticator - ) + service = cls(authenticator) service.configure_service(service_name) return service @@ -255,6 +253,7 @@ class IsDeleted(str, Enum): TRUE = 'true' FALSE = 'false' ANY = 'any' + class IsReclaimed(str, Enum): """ Determines if reclaimed documents should be included in result set or not. @@ -266,6 +265,7 @@ class IsReclaimed(str, Enum): TRUE = 'true' FALSE = 'false' ANY = 'any' + class CanTag(str, Enum): """ Determines if the result set must return the resources that the user can tag or @@ -277,6 +277,7 @@ class CanTag(str, Enum): TRUE = 'true' FALSE = 'false' + class IsProjectResource(str, Enum): """ Determines if documents belonging to Project family should be included in result @@ -339,9 +340,9 @@ def from_dict(cls, _dict: Dict) -> 'ResultItem': raise ValueError('Required property \'crn\' not present in ResultItem JSON') for k, v in _dict.items(): if k not in cls._properties: - if not isinstance(v, object): - raise ValueError('Value for additional property {} must be of type object'.format(k)) - args[k] = v + if not isinstance(v, object): + raise ValueError('Value for additional property {} must be of type object'.format(k)) + args[k] = v return cls(**args) @classmethod diff --git a/test/unit/test_global_search_v2.py b/test/unit/test_global_search_v2.py index 4b45bc75..4493957b 100644 --- a/test/unit/test_global_search_v2.py +++ b/test/unit/test_global_search_v2.py @@ -29,9 +29,7 @@ from ibm_platform_services.global_search_v2 import * -_service = GlobalSearchV2( - authenticator=NoAuthAuthenticator() -) +_service = GlobalSearchV2(authenticator=NoAuthAuthenticator()) _base_url = 'https://api.global-search-tagging.cloud.ibm.com' _service.set_service_url(_base_url)