diff --git a/sw360/__init__.py b/sw360/__init__.py index a1399e2..8c4cdc6 100644 --- a/sw360/__init__.py +++ b/sw360/__init__.py @@ -9,9 +9,9 @@ __version__ = (1, 11, 2) +from .base import SW360Response from .sorting import (BaseSortMixin, ProjectSortColumn, ReleaseSortColumn, SortParam) -from .base import SW360Response from .sw360_api import SW360 from .sw360error import SW360Error from .sw360keycloak import SW360Keycloak diff --git a/sw360/base.py b/sw360/base.py index 4afebf6..abcec49 100644 --- a/sw360/base.py +++ b/sw360/base.py @@ -130,6 +130,7 @@ def __init__(self, url: str, token: str, oauth2: bool = False, self.force_no_session = False self.default_batch_size = default_batch_size + self.api_version = (18, 0) def api_get(self, url: str = "") -> Optional[SW360Response]: """Request `url` from REST API and return json answer. @@ -373,7 +374,8 @@ def _update_external_ids(self, current_data: Dict[str, Any], ext_id_name: str, e return (old_value, ext_id_data, update) - def _add_params(self, url: str, params: Dict[str, str]) -> str: + @staticmethod + def _add_params(url: str, params: Dict[str, str]) -> str: """Add the given parameter to the given url""" query_string = urlencode(params) @@ -505,6 +507,17 @@ def _get_attachments( if '_links' in attachment: del attachment['_links'] return attachments + + def is_above_version_18(self) -> bool: + """Check if API version is above version 18. + Used to check version >= 19 features.""" + return self.api_version >= (19, 0) + + def is_above_version_19(self) -> bool: + """Check if API version is above version 19. + Used to check version >= 20 features.""" + return self.api_version >= (20, 0) + @classmethod def get_linked_id(cls, data: Dict[str, Any], link_key: str = "self") -> Optional[str]: """Extract the resource ID from a HAL ``_links`` entry. diff --git a/sw360/components.py b/sw360/components.py index f29d181..a7c1625 100644 --- a/sw360/components.py +++ b/sw360/components.py @@ -42,11 +42,15 @@ def __get_components_filtered( :raises SW360Error: if there is a negative HTTP response """ - full_url = self._add_params(url, {"luceneSearch": "true"}) + if self.is_above_version_18(): + full_url = self._add_params(url, {"luceneSearch": "true"}) + else: + full_url = url + if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) @@ -197,7 +201,10 @@ def get_component_by_name( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = ComponentSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = ComponentSortColumn.SCORE.asc() + else: + sort = ComponentSortColumn.NAME.asc() return self.__get_components_filtered(url_with_param, page, page_size, sort) diff --git a/sw360/license.py b/sw360/license.py index 12cac92..8a9f914 100644 --- a/sw360/license.py +++ b/sw360/license.py @@ -3,7 +3,7 @@ # Copyright (c) 2022 BMW CarIT GmbH # All Rights Reserved. # Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com -# Authors: helio.chissini-de-castro@bmw.de +# Authors: helio.chissini-de-castro@bmw.de, mishra.gaurav@siemens.com # # Licensed under the MIT license. # SPDX-License-Identifier: MIT @@ -133,7 +133,10 @@ def get_all_licenses(self) -> List[Dict[str, Any]]: """ fullbase_url = self.url + "resource/api/licenses" - resp = self.api_get_all(fullbase_url) + if self.is_above_version_18(): + resp = self.api_get_all(fullbase_url) + else: + resp = self.api_get(fullbase_url) if resp and "_embedded" in resp and "sw360:licenses" in resp["_embedded"]: return resp["_embedded"]["sw360:licenses"] diff --git a/sw360/moderationrequests.py b/sw360/moderationrequests.py index 79c2aa7..b2f902a 100644 --- a/sw360/moderationrequests.py +++ b/sw360/moderationrequests.py @@ -37,7 +37,10 @@ def get_all_moderation_requests( """ fullbase_url = self.url + "resource/api/moderationrequest" - params = {"luceneSearch": "true"} + if self.is_above_version_18(): + params = {"luceneSearch": "true"} + else: + params = {} if sort is None: sort = ModerationSortColumn.REQUEST_DATE.desc() @@ -46,7 +49,7 @@ def get_all_moderation_requests( if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) @@ -92,7 +95,7 @@ def get_moderation_requests_by_state( if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) diff --git a/sw360/packages.py b/sw360/packages.py index 90be6b7..b38f256 100644 --- a/sw360/packages.py +++ b/sw360/packages.py @@ -38,11 +38,15 @@ def __get_packages_filtered( :raises SW360Error: if there is a negative HTTP response """ - full_url = self._add_params(url, {"luceneSearch": "true"}) + if self.is_above_version_18(): + full_url = self._add_params(url, {"luceneSearch": "true"}) + else: + full_url = url + if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) @@ -100,7 +104,10 @@ def get_packages_by_name( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = PackageSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = PackageSortColumn.SCORE.asc() + else: + sort = PackageSortColumn.NAME.asc() return self.__get_packages_filtered(url_with_param, page, page_size, sort) @@ -155,7 +162,10 @@ def get_all_packages( if sort is None: sort = PackageSortColumn.NAME.asc() if name != "" or version != "" or purl != "": - sort = PackageSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = PackageSortColumn.SCORE.asc() + else: + sort = PackageSortColumn.NAME.asc() return self.__get_packages_filtered(url_with_param, page, page_size, sort) @@ -189,7 +199,10 @@ def get_packages_by_packagemanager( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = PackageSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = PackageSortColumn.SCORE.asc() + else: + sort = PackageSortColumn.NAME.asc() return self.__get_packages_filtered(url_with_param, page, page_size, sort) diff --git a/sw360/project.py b/sw360/project.py index 155b795..b8d92b4 100644 --- a/sw360/project.py +++ b/sw360/project.py @@ -55,7 +55,10 @@ def get_project_releases(self, project_id: str, transitive: bool = False) -> Any trans = "true" url = self.url + "resource/api/projects/" + project_id + "/releases" url = self._add_params(url, {"transitive": trans}) - resp = self.api_get_all(url, ReleaseSortColumn.CREATED_ON.desc()) + if self.is_above_version_18(): + resp = self.api_get_all(url, ReleaseSortColumn.CREATED_ON.desc()) + else: + resp = self.api_get(url) return resp def get_project_by_url(self, url: str) -> Optional[Dict[str, Any]]: @@ -97,11 +100,15 @@ def __get_projects_filtered( :raises SW360Error: if there is a negative HTTP response """ - full_url = self._add_params(url, {"luceneSearch": "true"}) + if self.is_above_version_18(): + full_url = self._add_params(url, {"luceneSearch": "true"}) + else: + full_url = url + if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) @@ -237,7 +244,10 @@ def get_projects_by_name( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = ProjectSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = ProjectSortColumn.SCORE.asc() + else: + sort = ProjectSortColumn.NAME.asc() return self.__get_projects_filtered(url_with_param, page, page_size, sort) @@ -311,7 +321,10 @@ def get_projects_by_group( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = ProjectSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = ProjectSortColumn.SCORE.asc() + else: + sort = ProjectSortColumn.NAME.asc() return self.__get_projects_filtered(url_with_param, page, page_size, sort) @@ -345,7 +358,10 @@ def get_projects_by_tag( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = ProjectSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = ProjectSortColumn.SCORE.asc() + else: + sort = ProjectSortColumn.NAME.asc() return self.__get_projects_filtered(url_with_param, page, page_size, sort) @@ -365,7 +381,10 @@ def get_project_vulnerabilities(self, project_id: str) -> Optional[Dict[str, Any raise SW360Error(message="No project id provided!") full_url = self.url + "resource/api/projects/" + project_id + "/vulnerabilities" - resp = self.api_get_all(full_url) + if self.is_above_version_18(): + resp = self.api_get_all(full_url) + else: + resp = self.api_get(full_url) if not resp: return None diff --git a/sw360/releases.py b/sw360/releases.py index 5bed6cd..e5aec8c 100644 --- a/sw360/releases.py +++ b/sw360/releases.py @@ -3,7 +3,7 @@ # Copyright (c) 2022 BMW CarIT GmbH # All Rights Reserved. # Authors: thomas.graf@siemens.com, gernot.hillier@siemens.com -# Authors: helio.chissini-de-castro@bmw.de +# Authors: helio.chissini-de-castro@bmw.de, mishra.gaurav@siemens.com # # Licensed under the MIT license. # SPDX-License-Identifier: MIT @@ -40,18 +40,22 @@ def __get_releases_filtered( :raises SW360Error: if there is a negative HTTP response """ - full_url = self._add_params(url, {"luceneSearch": "true"}) + if self.is_above_version_18(): + full_url = self._add_params(url, {"luceneSearch": "true"}) + else: + full_url = url + if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) if (resp and "_embedded" in resp and - "sw360:releases" in resp["_embedded"]): + "sw360:releases" in resp["_embedded"]): return resp["_embedded"]["sw360:releases"] return [] @@ -119,7 +123,10 @@ def get_releases_by_name( url_with_param = self._add_params(fullbase_url, params) if sort is None: - sort = ReleaseSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = ReleaseSortColumn.SCORE.asc() + else: + sort = ReleaseSortColumn.VERSION.desc() return self.__get_releases_filtered(url_with_param, page, page_size, sort) @@ -420,8 +427,8 @@ def upload_attachment_to_release( raise SW360Error(message="No release id provided!") attachment_content = self._upload_resource_file(upload_file, upload_type, upload_comment) - attachment_content['attachmentType'] = upload_type # Make sure the type is correct - attachment_content['createdComment'] = upload_comment # Override + attachment_content['attachmentType'] = upload_type # Make sure the type is correct + attachment_content['createdComment'] = upload_comment # Override current_release = self.get_release(release_id) attachments = self._get_attachments(current_release) diff --git a/sw360/reports.py b/sw360/reports.py index 163ae7d..d3848e5 100644 --- a/sw360/reports.py +++ b/sw360/reports.py @@ -7,8 +7,6 @@ # SPDX-License-Identifier: MIT # ------------------------------------------------------------------------------- -from typing import Any, Dict, List, Optional - import requests from .base import BaseMixin @@ -37,6 +35,9 @@ def generate_project_license_info( :rtype: int :raises SW360Error: if there is a negative HTTP response """ + if not self.is_above_version_18(): + raise SW360Error(message="SW360 version < 19 is not supported") + if not project_id: raise SW360Error(message="No project id provided!") @@ -97,6 +98,9 @@ def generate_project_clearing_report( :rtype: int :raises SW360Error: if there is a negative HTTP response """ + if not self.is_above_version_18(): + raise SW360Error(message="SW360 version < 19 is not supported") + if not project_id: raise SW360Error(message="No project id provided!") @@ -148,6 +152,9 @@ def generate_project_source_code_bundle( :type with_subprojects: bool :raises SW360Error: if there is a negative HTTP response """ + if not self.is_above_version_18(): + raise SW360Error(message="SW360 version < 19 is not supported") + if not project_id: raise SW360Error(message="No project id provided!") diff --git a/sw360/sorting.py b/sw360/sorting.py index c9a36a0..02a63dd 100644 --- a/sw360/sorting.py +++ b/sw360/sorting.py @@ -79,11 +79,13 @@ class PackageSortColumn(BaseSortMixin, Enum): VERSION = "version" PACKAGE_MANAGER = "packageManager" + class VendorSortColumn(BaseSortMixin, Enum): SCORE = "score" FULL_NAME = "fullName" SHORT_NAME = "shortName" + class VulnerabilitySortColumn(BaseSortMixin, Enum): LAST_UPDATE_DATE = "lastUpdateDate" EXTERNAL_ID = "externalId" diff --git a/sw360/sw360_api.py b/sw360/sw360_api.py index 65bde29..f81a4f8 100644 --- a/sw360/sw360_api.py +++ b/sw360/sw360_api.py @@ -10,7 +10,7 @@ """Python interface to the Siemens SW360 platform""" -from typing import Any, Dict, Optional +from typing import Any, Dict, Optional, Tuple import requests from requests.adapters import HTTPAdapter @@ -73,6 +73,7 @@ class SW360( :type oauth2: boolean :ivar default_batch_size: Default size of batch to use while fetching all items from API :type default_batch_size: int + :ivar api_version: SW360 API Version, defaults to 18.0 """ def __init__( @@ -98,8 +99,9 @@ def __init__( self.force_no_session = False self.default_batch_size = default_batch_size + self.api_version = self.parse_version("18.0") - def login_api(self, token: str = "") -> bool: + def login_api(self, token: str = "") -> bool: # noqa """Login to SW360 REST API. This used to have a `token` parameter due to historic reasons which is ignored. @@ -121,6 +123,24 @@ def login_api(self, token: str = "") -> bool: except Exception as ex: raise SW360Error(None, url, message="Unable to login: " + repr(ex)) + version_url = self.url + "resource/api/version" + try: + if self.force_no_session: + versp = requests.get(version_url, + headers={"Accept": "application/json"}) + else: + if self.session: + versp = self.session.get( + version_url, + headers={"Accept": "application/json"}) + version_response = versp.json() + if "apiVersion" not in version_response: + raise SW360Error(versp, version_url, + "Unable to get API version") + self.api_version = self.parse_version(version_response["apiVersion"]) + except Exception: + self.api_version = self.parse_version("18.0") + if resp.ok: return True else: @@ -169,9 +189,13 @@ def get_health_status(self) -> Optional[Dict[str, Any]]: :rtype: JSON health status object :raises SW360Error: if there is a negative HTTP response """ - try: - # SW360 >= 19.0 has changed the endpoint path - return self.api_get(self.url + "resource/api/health/") - except SW360Error: - # try to fallback to old endpoint for SW360 <= 18.x + if self.is_above_version_18(): + return self.api_get(self.url + "resource/api/health") + else: return self.api_get(self.url + "resource/health/") + + @staticmethod + def parse_version(version_string: str) -> Tuple[int, int]: + """Extract major.minor as comparable tuple""" + parts = version_string.split('.') + return (int(parts[0]), int(parts[1])) diff --git a/sw360/sw360error.py b/sw360/sw360error.py index 350ecf7..1bed794 100644 --- a/sw360/sw360error.py +++ b/sw360/sw360error.py @@ -42,3 +42,15 @@ def __init__(self, response: Optional[Response] = None, url: str = "", message: super().__init__(message) else: super().__init__(str(response)) + + def __str__(self) -> str: + return_str = "Operation failed " + if self.message != "": + return_str = f"{self.message} " + if self.url != "": + return_str += f"for '{self.url}' " + if self.response is not None: + return_str += f"with status code {self.response.status_code}. " + if self.details is not None: + return_str += f"Response body: {self.details}" + return return_str.strip() diff --git a/sw360/vendor.py b/sw360/vendor.py index 8906cc8..b685a62 100644 --- a/sw360/vendor.py +++ b/sw360/vendor.py @@ -44,7 +44,7 @@ def get_all_vendors( if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) @@ -81,13 +81,16 @@ def search_vendors( params = {"searchText": search_text} if sort is None: - sort = VendorSortColumn.SCORE.asc() + if self.is_above_version_18(): + sort = VendorSortColumn.SCORE.asc() + else: + sort = VendorSortColumn.SHORT_NAME.asc() full_url = self._add_params(fullbase_url, params) if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) diff --git a/sw360/vulnerabilities.py b/sw360/vulnerabilities.py index 616ba98..b998fd9 100644 --- a/sw360/vulnerabilities.py +++ b/sw360/vulnerabilities.py @@ -57,7 +57,7 @@ def get_all_vulnerabilities( if page > -1 and page_size > -1: full_url = self._add_pagination(full_url, page, page_size, sort) - if page_size == -1: + if self.is_above_version_18() and page_size == -1: resp = self.api_get_all(full_url, sort) else: resp = self.api_get(full_url) diff --git a/tests/test_sw360_clearingrequests.py b/tests/test_sw360_clearingrequests.py index 8d5552f..7d22a31 100644 --- a/tests/test_sw360_clearingrequests.py +++ b/tests/test_sw360_clearingrequests.py @@ -41,10 +41,24 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997"' + + ',"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + @responses.activate def test_get_clearing_request(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -69,6 +83,7 @@ def test_get_clearing_request(self) -> None: def test_get_clearing_request_for_project(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) diff --git a/tests/test_sw360_components.py b/tests/test_sw360_components.py index 4895919..8205f68 100644 --- a/tests/test_sw360_components.py +++ b/tests/test_sw360_components.py @@ -44,6 +44,19 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + def _my_matcher(self) -> Any: """ Helper method to display the JSON parameters of a REST call. @@ -59,6 +72,7 @@ def test_get_all_components(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -81,6 +95,7 @@ def test_get_all_components_no_result(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -101,6 +116,7 @@ def test_get_all_components_with_fields(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -124,6 +140,7 @@ def test_get_all_components_with_fields_and_paging(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( @@ -146,6 +163,7 @@ def test_get_all_components_with_all_details(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -164,11 +182,35 @@ def test_get_all_components_with_all_details(self) -> None: self.assertEqual("Tethys.Logging", components[0]["name"]) self.assertEqual("DE", components[0]["ownerCountry"]) + @responses.activate + def test_get_all_components_with_all_details_v18_style(self) -> None: + lib = SW360(self.MYURL, self.MYTOKEN, False) + lib.force_no_session = True + self._add_login_response() + actual = lib.login_api() + self.assertTrue(actual) + + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/components?allDetails=true", # noqa + body='{"_embedded": {"sw360:components": [{"name": "Tethys.Logging", "ownerCountry": "DE", "componentType": "OSS", "externalIds": {"package-url": "pkg:nuget/Tethys.Logging"}}]}}', # noqa + status=200, + content_type="application/json", + adding_headers={"Authorization": "Token " + self.MYTOKEN}, + ) + + components = lib.get_all_components(all_details=True) + self.assertIsNotNone(components) + self.assertTrue(len(components) > 0) + self.assertEqual("Tethys.Logging", components[0]["name"]) + self.assertEqual("DE", components[0]["ownerCountry"]) + @responses.activate def test_get_all_components_with_all_details_and_sorting(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -192,6 +234,7 @@ def test_get_all_components_invalid_reply(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -213,6 +256,7 @@ def test_get_all_components_invalid_reply2(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -234,6 +278,7 @@ def test_get_all_components_by_type(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -257,6 +302,7 @@ def test_get_all_components_by_type_no_result(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -277,6 +323,7 @@ def test_get_all_components_by_type_invalid_reply(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -298,6 +345,7 @@ def test_get_all_components_by_type_invalid_reply2(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -319,6 +367,7 @@ def test_get_component(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -340,6 +389,7 @@ def test_get_component_by_url(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -361,6 +411,7 @@ def test_get_component_by_name(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -383,6 +434,7 @@ def test_get_components_by_external_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -405,6 +457,7 @@ def test_get_components_by_external_id_full_answer(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -427,6 +480,7 @@ def test_get_components_by_external_id_invalid_answer(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -448,6 +502,7 @@ def test_update_component_external_id_add_fresh_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -480,6 +535,7 @@ def test_update_component_external_id_no_overwrite(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -503,6 +559,7 @@ def test_update_component_external_id_overwrite(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -536,6 +593,7 @@ def test_update_component_external_id_delete(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -569,6 +627,7 @@ def test_update_component_external_id_no_exist(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -606,6 +665,7 @@ def test_update_component_external_id_no_extids_yet(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -638,6 +698,7 @@ def test_create_new_component(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -674,6 +735,7 @@ def test_create_new_component_fail(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -717,6 +779,7 @@ def test_update_component_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -733,6 +796,7 @@ def test_update_component_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -762,6 +826,7 @@ def test_delete_component(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -779,6 +844,7 @@ def test_delete_component_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -792,6 +858,7 @@ def test_delete_component_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -818,6 +885,7 @@ def test_get_users_of_component(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -848,6 +916,7 @@ def test_get_recent_components(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) diff --git a/tests/test_sw360_health.py b/tests/test_sw360_health.py index 6e6723d..6f4dc32 100644 --- a/tests/test_sw360_health.py +++ b/tests/test_sw360_health.py @@ -41,16 +41,30 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + @responses.activate def test_get_health_status(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( method=responses.GET, - url=self.MYURL + "resource/api/health/", + url=self.MYURL + "resource/api/health", body='{"status": "UP"}', status=200, content_type="application/json", @@ -69,13 +83,6 @@ def test_get_health_status_pre_v19_fallback(self) -> None: actual = lib.login_api() self.assertTrue(actual) - responses.add( - method=responses.GET, - url=self.MYURL + "resource/api/health/", - body='{"status":404,"error":"Not Found","path":"/resource/api/health/"}', - status=404, - ) - responses.add( method=responses.GET, url=self.MYURL + "resource/health/", diff --git a/tests/test_sw360_licenses.py b/tests/test_sw360_licenses.py index 992ce64..ab27e22 100644 --- a/tests/test_sw360_licenses.py +++ b/tests/test_sw360_licenses.py @@ -41,10 +41,24 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + @responses.activate def test_get_all_licenses(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -80,6 +94,7 @@ def test_get_all_licenses(self) -> None: def test_get_all_licenses_none(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -99,6 +114,7 @@ def test_get_all_licenses_none(self) -> None: def test_get_license(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -128,6 +144,7 @@ def test_get_license(self) -> None: def test_create_new_license(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -163,6 +180,7 @@ def test_create_new_license(self) -> None: def test_create_new_license_fail(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -208,6 +226,7 @@ def test_create_new_license_fail(self) -> None: def test_delete_license(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) diff --git a/tests/test_sw360_moderationrequests.py b/tests/test_sw360_moderationrequests.py index 2b8e487..2799a7d 100644 --- a/tests/test_sw360_moderationrequests.py +++ b/tests/test_sw360_moderationrequests.py @@ -42,10 +42,24 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + @responses.activate def test_get_all_moderation_requests(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -117,6 +131,7 @@ def test_get_all_moderation_requests(self) -> None: def test_get_moderation_requests_by_state(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -189,6 +204,7 @@ def test_get_moderation_requests_by_state(self) -> None: def test_get_license(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) diff --git a/tests/test_sw360_packages.py b/tests/test_sw360_packages.py index 7f7c9cf..c12b5a2 100644 --- a/tests/test_sw360_packages.py +++ b/tests/test_sw360_packages.py @@ -43,6 +43,19 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + def _my_matcher(self) -> Any: """ Helper method to display the JSON parameters of a REST call. @@ -57,6 +70,7 @@ def display_json_params(request_body: Any) -> bool: def test_get_get_packages(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -79,6 +93,7 @@ def test_get_get_packages(self) -> None: def test_get_all_packages(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -102,6 +117,7 @@ def test_get_all_packages(self) -> None: def test_get_all_packages_with_fields_and_all_details(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -126,6 +142,7 @@ def test_get_all_packages_with_fields_and_all_details(self) -> None: def test_get_all_packages_with_fields_and_all_details2(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -149,6 +166,7 @@ def test_get_all_packages_with_fields_and_all_details2(self) -> None: def test_get_packages_by_name(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -172,6 +190,7 @@ def test_get_packages_by_name(self) -> None: def test_get_packages_by_packagemanager(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -195,6 +214,7 @@ def test_get_packages_by_packagemanager(self) -> None: def test_get_packages_by_packagemanager_with_details(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -219,6 +239,7 @@ def test_create_new_package(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -250,6 +271,7 @@ def test_create_new_package_already_exists(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -290,6 +312,7 @@ def test_update_package(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -311,6 +334,7 @@ def test_update_package_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -334,6 +358,7 @@ def test_update_package_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -363,6 +388,7 @@ def test_delete_package(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -379,6 +405,7 @@ def test_delete_package(self) -> None: def test_delete_package_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -391,6 +418,7 @@ def test_delete_package_no_id(self) -> None: def test_delete_package_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) diff --git a/tests/test_sw360_projects.py b/tests/test_sw360_projects.py index 8164473..61a7379 100644 --- a/tests/test_sw360_projects.py +++ b/tests/test_sw360_projects.py @@ -42,6 +42,14 @@ def get_logged_in_lib(self) -> SW360: content_type="application/json", adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) actual = lib.login_api() self.assertTrue(actual) @@ -201,6 +209,25 @@ def test_get_projects(self) -> None: if projects: # only for mypy self.assertEqual("My Testproject", projects[0]["name"]) + @responses.activate + def test_get_projects_v18_style(self) -> None: + lib = self.get_logged_in_lib() + lib.api_version = (18, 0) + + responses.add( + responses.GET, + url=self.MYURL + "resource/api/projects", + body='{"_embedded": {"sw360:projects": [{"name": "My Testproject"}]}}', + status=200, + content_type="application/json", + adding_headers={"Authorization": "Token " + self.MYTOKEN}, + ) + + projects = lib.get_projects() + self.assertIsNotNone(projects) + if projects: # only for mypy + self.assertEqual("My Testproject", projects[0]["name"]) + @responses.activate def test_get_projects_with_details(self) -> None: lib = self.get_logged_in_lib() diff --git a/tests/test_sw360_releases.py b/tests/test_sw360_releases.py index d6974de..183e8ca 100644 --- a/tests/test_sw360_releases.py +++ b/tests/test_sw360_releases.py @@ -43,6 +43,19 @@ def _add_login_response(self) -> None: adding_headers={"Authorization": "Token " + self.MYTOKEN}, ) + def _add_version_response(self) -> None: + """ + Add the response for a successful login. + """ + responses.add( + method=responses.GET, + url=self.MYURL + "resource/api/version", + body='{"apiVersion":"20.1.76","buildTime":"2026-08-14T13:17:47Z","buildNumber":"a8a0997",' + + '"sw360Version":"20.1.0","gitBranch":"main"}', + status=200, + content_type="application/json", + ) + def _my_matcher(self) -> Any: """ Helper method to display the JSON parameters of a REST call. @@ -57,6 +70,7 @@ def display_json_params(request_body: Any) -> bool: def test_get_get_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -79,13 +93,15 @@ def test_get_get_release(self) -> None: def test_get_get_release_internal_server_error(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( method=responses.GET, url=self.MYURL + "resource/api/releases/123", - body='{"timestamp": "2020-12-10T07:22:06.1685Z", "status": "500", "error": "Internal Server Error", "message": "Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Metaspace"}', # noqa + body='{"timestamp": "2020-12-10T07:22:06.1685Z", "status": "500", "error": "Internal Server Error",' + + ' "message": "Handler dispatch failed; nested exception is java.lang.OutOfMemoryError: Metaspace"}', # noqa status=500, content_type="application/json", adding_headers={"Authorization": "Token " + self.MYTOKEN}, @@ -109,6 +125,7 @@ def test_get_get_release_internal_server_error(self) -> None: def test_get_release_by_url(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -131,6 +148,7 @@ def test_get_release_by_url(self) -> None: def test_get_all_releases(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -157,12 +175,15 @@ def test_get_all_releases_isnewclearing_with_source_available(self) -> None: """ lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( method=responses.GET, - url=self.MYURL + "resource/api/releases?isNewClearingWithSourceAvailable=true&luceneSearch=true&page=0&page_entries=50&sort=name,asc", + url=self.MYURL + + "resource/api/releases?isNewClearingWithSourceAvailable=true&luceneSearch=true" + + "&page=0&page_entries=50&sort=name,asc", body='{"_embedded": {"sw360:releases": [{"name": "Tethys.Logging", "version": "1.3.0"}]}}', status=200, content_type="application/json", @@ -179,6 +200,30 @@ def test_get_all_releases_isnewclearing_with_source_available(self) -> None: @responses.activate def test_get_all_releases_all_details(self) -> None: + lib = SW360(self.MYURL, self.MYTOKEN, False) + self._add_login_response() + self._add_version_response() + actual = lib.login_api() + self.assertTrue(actual) + + responses.add( + method=responses.GET, + url=self.MYURL + + "resource/api/releases?allDetails=true&luceneSearch=true&page=0&page_entries=50&sort=name,asc", + body='{"_embedded": {"sw360:releases": [{"name": "Tethys.Logging", "version": "1.3.0", "releaseDate": "2018-03-04"}]}}', # noqa + status=200, + content_type="application/json", + adding_headers={"Authorization": "Token " + self.MYTOKEN}, + ) + + releases = lib.get_all_releases("", True) + self.assertIsNotNone(releases) + self.assertTrue(len(releases) > 0) + self.assertEqual("Tethys.Logging", releases[0]["name"]) + self.assertEqual("1.3.0", releases[0]["version"]) + + @responses.activate + def test_get_all_releases_all_details_v18_style(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() actual = lib.login_api() @@ -186,7 +231,7 @@ def test_get_all_releases_all_details(self) -> None: responses.add( method=responses.GET, - url=self.MYURL + "resource/api/releases?allDetails=true&luceneSearch=true&page=0&page_entries=50&sort=name,asc", + url=self.MYURL + "resource/api/releases?allDetails=true", body='{"_embedded": {"sw360:releases": [{"name": "Tethys.Logging", "version": "1.3.0", "releaseDate": "2018-03-04"}]}}', # noqa status=200, content_type="application/json", @@ -203,12 +248,14 @@ def test_get_all_releases_all_details(self) -> None: def test_get_all_releases_with_fields(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( method=responses.GET, - url=self.MYURL + "resource/api/releases?fields=releaseDate&luceneSearch=true&page=0&page_entries=50&sort=name,asc", + url=self.MYURL + + "resource/api/releases?fields=releaseDate&luceneSearch=true&page=0&page_entries=50&sort=name,asc", body='{"_embedded": {"sw360:releases": [{"name": "Tethys.Logging", "version": "1.3.0", "releaseDate": "2018-03-04"}]}}', # noqa status=200, content_type="application/json", @@ -225,12 +272,15 @@ def test_get_all_releases_with_fields(self) -> None: def test_get_all_releases_with_fields_and_all_details(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) responses.add( method=responses.GET, - url=self.MYURL + "resource/api/releases?allDetails=true&fields=releaseDate&luceneSearch=true&page=0&page_entries=50&sort=name,asc", + url=self.MYURL + + "resource/api/releases?allDetails=true&fields=releaseDate&luceneSearch=true" + + "&page=0&page_entries=50&sort=name,asc", body='{"_embedded": {"sw360:releases": [{"name": "Tethys.Logging", "version": "1.3.0", "releaseDate": "2018-03-04"}]}}', # noqa status=200, content_type="application/json", @@ -247,6 +297,7 @@ def test_get_all_releases_with_fields_and_all_details(self) -> None: def test_get_all_releases_with_paging_and_sorting(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -269,6 +320,7 @@ def test_get_all_releases_with_paging_and_sorting(self) -> None: def test_get_releases_by_external_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -291,6 +343,7 @@ def test_get_releases_by_external_id(self) -> None: def test_get_releases_by_external_id_invalid_reply(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -311,6 +364,7 @@ def test_get_releases_by_external_id_invalid_reply(self) -> None: def test_get_releases_by_name(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -333,6 +387,7 @@ def test_get_releases_by_name(self) -> None: def test_get_releases_by_name_invalid_answer(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -354,6 +409,7 @@ def test_create_new_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -387,6 +443,7 @@ def test_create_new_release_already_exists(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -429,6 +486,7 @@ def test_update_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -450,6 +508,7 @@ def test_update_release_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -473,6 +532,7 @@ def test_update_release_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -501,6 +561,7 @@ def test_update_release_failed(self) -> None: def test_update_release_external_id_add_fresh_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -533,6 +594,7 @@ def test_delete_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -549,6 +611,7 @@ def test_delete_release(self) -> None: def test_delete_release_no_id(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -561,6 +624,7 @@ def test_delete_release_no_id(self) -> None: def test_delete_release_failed(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -586,6 +650,7 @@ def test_delete_release_failed(self) -> None: def test_get_users_of_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -605,6 +670,7 @@ def test_link_packages_to_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -631,6 +697,7 @@ def test_unlink_packages_from_release(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) lib.force_no_session = True self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual) @@ -656,6 +723,7 @@ def test_unlink_packages_from_release_no_id(self) -> None: def test_get_recent_releases(self) -> None: lib = SW360(self.MYURL, self.MYTOKEN, False) self._add_login_response() + self._add_version_response() actual = lib.login_api() self.assertTrue(actual)