diff --git a/.github/workflows/fossologytests.yml b/.github/workflows/fossologytests.yml index 35064fa..897a5bb 100644 --- a/.github/workflows/fossologytests.yml +++ b/.github/workflows/fossologytests.yml @@ -10,7 +10,7 @@ on: jobs: test-latest: - name: Integration Tests (latest Fossology - 4.3.0) + name: Integration Tests (latest Fossology - 4.4.0-rc1) runs-on: ubuntu-latest container: @@ -20,7 +20,7 @@ jobs: services: fossology: - image: fossology/fossology:4.3.0 + image: fossology/fossology:4.4.0-rc1 ports: - 8081:80 volumes: diff --git a/fossology/__init__.py b/fossology/__init__.py index a1567fa..68c0aa0 100644 --- a/fossology/__init__.py +++ b/fossology/__init__.py @@ -10,6 +10,7 @@ from fossology.exceptions import AuthenticationError, FossologyApiError from fossology.folders import Folders from fossology.groups import Groups +from fossology.items import Items from fossology.jobs import Jobs from fossology.license import LicenseEndpoint from fossology.obj import Agents, ApiInfo, HealthInfo, User @@ -79,7 +80,9 @@ def fossology_token( exit(f"Server {url} does not seem to be running or is unreachable: {error}") -class Fossology(Folders, Groups, LicenseEndpoint, Uploads, Jobs, Report, Users, Search): +class Fossology( + Folders, Groups, Items, LicenseEndpoint, Uploads, Jobs, Report, Users, Search +): """Main Fossology API class @@ -104,7 +107,7 @@ def __init__(self, url, token, name=None): self.users = list() self.folders = list() - self.api = f"{self.host}/api/v1" + self.api = f"{self.host}/api/v2" self.session = requests.Session() self.session.headers.update({"Authorization": f"Bearer {self.token}"}) self.info = self.get_info() diff --git a/fossology/enums.py b/fossology/enums.py index 19a0e47..d33e974 100644 --- a/fossology/enums.py +++ b/fossology/enums.py @@ -195,3 +195,14 @@ class PrevNextSelection(Enum): WITHLICENSES = "withLicenses" NOCLEARING = "noClearing" + + +class CopyrightStatus(Enum): + """Status of the copyrights: + + ACTIVE + INACTIVE + """ + + ACTIVE = "active" + INACTIVE = "inactive" diff --git a/fossology/items.py b/fossology/items.py new file mode 100644 index 0000000..b6efb4f --- /dev/null +++ b/fossology/items.py @@ -0,0 +1,253 @@ +# mypy: disable-error-code="attr-defined" +# Copyright 2019 Siemens AG +# SPDX-License-Identifier: MIT +import json +import logging + +from fossology.enums import CopyrightStatus, PrevNextSelection +from fossology.exceptions import FossologyApiError +from fossology.obj import ( + FileInfo, + GetBulkHistory, + GetClearingHistory, + GetPrevNextItem, + Upload, +) + +logger = logging.getLogger(__name__) +logger.setLevel(logging.DEBUG) + + +class Items: + """Class dedicated to all "uploads...items" related endpoints""" + + def item_info( + self, + upload: Upload, + item_id: int, + ) -> FileInfo: + """Get the info for a specific upload item + + API Endpoint: GET /uploads/{id}/item/{itemId}/info + + :param upload: the upload to get items from + :param item_id: the id of the item + :type upload: Upload + :type item_id: int, + :return: the file info for the specified item + :rtype: FileInfo + :raises FossologyApiError: if the REST call failed + """ + response = self.session.get( + f"{self.api}/uploads/{upload.id}/item/{item_id}/info" + ) + + if response.status_code == 200: + return FileInfo.from_json(response.json()) + + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while getting info for item {item_id} from upload {upload.uploadname}" + raise FossologyApiError(description, response) + + def item_copyrights( + self, + upload: Upload, + item_id: int, + status: CopyrightStatus, + ) -> int: + """Get the total copyrights of the mentioned upload tree ID + + API Endpoint: GET /uploads/{id}/item/{itemId}/totalcopyrights + + :param upload: the upload to get items from + :param item_id: the id of the item + :param status: the status of the copyrights + :type upload: Upload + :type item_id: int, + :return: the total number of copyrights for the uploadtree item + :rtype: int + :raises FossologyApiError: if the REST call failed + """ + response = self.session.get( + f"{self.api}/uploads/{upload.id}/item/{item_id}/totalcopyrights?status={status.value}" + ) + + if response.status_code == 200: + return response.json()["total_copyrights"] + + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while getting total copyrights for item {item_id} from upload {upload.uploadname}." + raise FossologyApiError(description, response) + + def get_clearing_history( + self, + upload: Upload, + item_id: int, + ) -> list[GetClearingHistory]: + """Get the clearing history for a specific upload item + + API Endpoint: GET /uploads/{id}/item/{itemId}/clearing-history + + :param upload: the upload to get items from + :param item_id: the id of the item with clearing decision + :type upload: Upload + :type item_id: int, + :return: the clearing history for the specified item + :rtype: List[GetClearingHistory] + :raises FossologyApiError: if the REST call failed + :raises AuthorizationError: if the REST call is not authorized + """ + response = self.session.get( + f"{self.api}/uploads/{upload.id}/item/{item_id}/clearing-history" + ) + + if response.status_code == 200: + clearing_history = [] + for action in response.json(): + clearing_history.append(GetClearingHistory.from_json(action)) + return clearing_history + + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while getting clearing history for item {item_id} from upload {upload.uploadname}." + raise FossologyApiError(description, response) + + def get_prev_next( + self, upload: Upload, item_id: int, selection: PrevNextSelection | None = None + ) -> GetPrevNextItem: + """Get the index of the previous and the next time for an upload + + API Endpoint: GET /uploads/{id}/item/{itemId}/prev-next + + :param upload: the upload to get items from + :param item_id: the id of the item with clearing decision + :param selection: tell Fossology server how to select prev-next item + :type upload: Upload + :type item_id: int + :type selection: str + :return: list of items for the clearing history + :rtype: List[GetPrevNextItem] + :raises FossologyApiError: if the REST call failed + :raises AuthorizationError: if the REST call is not authorized + """ + params = {} + if selection: + params["selection"] = selection + + response = self.session.get( + f"{self.api}/uploads/{upload.id}/item/{item_id}/prev-next", params=params + ) + + if response.status_code == 200: + return GetPrevNextItem.from_json(response.json()) + + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while getting prev-next items for {item_id} from upload {upload.uploadname}." + raise FossologyApiError(description, response) + + def get_bulk_history( + self, + upload: Upload, + item_id: int, + ) -> list[GetBulkHistory]: + """Get the bulk history for a specific upload item + + API Endpoint: GET /uploads/{id}/item/{itemId}/bulk-history + + :param upload: the upload to get items from + :param item_id: the id of the item with clearing decision + :type upload: Upload + :type item_id: int + :return: list of data from the bulk history + :rtype: List[GetBulkHistory] + :raises FossologyApiError: if the REST call failed + :raises AuthorizationError: if the REST call is not authorized + """ + response = self.session.get( + f"{self.api}/uploads/{upload.id}/item/{item_id}/bulk-history" + ) + + if response.status_code == 200: + bulk_history = [] + for item in response.json(): + bulk_history.append(GetBulkHistory.from_json(item)) + return bulk_history + + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while getting bulk history for {item_id} from upload {upload.uploadname}." + raise FossologyApiError(description, response) + + def schedule_bulk_scan( + self, + upload: Upload, + item_id: int, + spec: dict, + ): + """Schedule a bulk scan for a specific upload item + + API Endpoint: POST /uploads/{id}/item/{itemId}/bulk-scan + + Bulk scan specifications `spec` are added to the request body, + following options are available: + + >>> bulk_scan_spec = { + ... "bulkActions": [ + ... { + ... "licenseShortName": 'MIT', + ... "licenseText": 'License text', + ... "acknowledgement": 'Acknowledgment text', + ... "comment": 'Comment text', + ... "licenseAction": 'ADD', # or 'REMOVE' + ... } + ... ], + ... "refText": 'Reference Text', + ... "bulkScope": 'folder', # or upload + ... "forceDecision": 'false', + ... "ignoreIrre": 'false', + ... "delimiters": 'DEFAULT', + ... "scanOnlyFindings": 'true', + ... } + + :param upload: the upload for the bulk scan + :param item_id: the id of the item for the bulk scan + :param spec: bulk scan specification + :type upload: Upload + :type item_id: int + :raises FossologyApiError: if the REST call failed + :raises AuthorizationError: if the REST call is not authorized + """ + headers = {"Content-Type": "application/json"} + response = self.session.post( + f"{self.api}/uploads/{upload.id}/item/{item_id}/bulk-scan", + headers=headers, + data=json.dumps(spec), + ) + if response.status_code == 201: + logger.info( + f"Bulk scan scheduled for upload {upload.uploadname}, item {item_id}" + ) + elif response.status_code == 400: + description = ( + f"Bad bulk scan request for upload {upload.id}, item {item_id}" + ) + raise FossologyApiError(description, response) + elif response.status_code == 404: + description = f"Upload {upload.id} or item {item_id} not found" + raise FossologyApiError(description, response) + else: + description = f"API error while scheduling bulk scan for item {item_id} from upload {upload.uploadname}." + raise FossologyApiError(description, response) diff --git a/fossology/obj.py b/fossology/obj.py index 44c808f..ae40462 100644 --- a/fossology/obj.py +++ b/fossology/obj.py @@ -530,6 +530,50 @@ def from_json(cls, json_dict): return cls(**json_dict) +class FileInfo(object): + + """FOSSology file info response. + + Represents a FOSSology file info response. + + :param view_info: view info of the file + :param meta_info: meta info of the file + :param package_info: package info of the file + :param tag_info: tag info of the file + :param reuse_info: reuse info of the file + :param kwargs: handle any other license information provided by the fossology instance + :type view_info: Object + :type meta_info: Object + :type package_info: Object + :type tag_info: Object + :type reuse_info: Object + :type kwargs: key word argument + """ + + def __init__( + self, + view_info, + meta_info, + package_info, + tag_info, + reuse_info, + **kwargs, + ): + self.view_info = view_info + self.meta_info = meta_info + self.package_info = package_info + self.tag_info = tag_info + self.reuse_info = reuse_info + self.additional_info = kwargs + + def __str__(self): + return f"File view {self.view_info}" + + @classmethod + def from_json(cls, json_dict): + return cls(**json_dict) + + class Upload(object): """FOSSology upload. diff --git a/fossology/uploads.py b/fossology/uploads.py index de96ae2..98ba3fe 100644 --- a/fossology/uploads.py +++ b/fossology/uploads.py @@ -10,13 +10,10 @@ import requests from tenacity import TryAgain, retry, retry_if_exception_type, stop_after_attempt -from fossology.enums import AccessLevel, ClearingStatus, PrevNextSelection +from fossology.enums import AccessLevel, ClearingStatus from fossology.exceptions import AuthorizationError, FossologyApiError from fossology.obj import ( Folder, - GetBulkHistory, - GetClearingHistory, - GetPrevNextItem, Group, Permission, Summary, @@ -792,170 +789,3 @@ def upload_permissions( f"API error while getting permissions for upload {upload.uploadname}." ) raise FossologyApiError(description, response) - - def get_clearing_history( - self, - upload: Upload, - item_id: int, - ) -> list[GetClearingHistory]: - """Get the clearing history for a specific upload item - - API Endpoint: GET /uploads/{id}/item/{itemId}/clearing-history - - :param upload: the upload to get items from - :param item_id: the id of the item with clearing decision - :type upload: Upload - :type item_id: int, - :return: the clearing history for the specified item - :rtype: List[GetClearingHistory] - :raises FossologyApiError: if the REST call failed - :raises AuthorizationError: if the REST call is not authorized - """ - response = self.session.get( - f"{self.api}/uploads/{upload.id}/item/{item_id}/clearing-history" - ) - - if response.status_code == 200: - clearing_history = [] - for action in response.json(): - clearing_history.append(GetClearingHistory.from_json(action)) - return clearing_history - - elif response.status_code == 404: - description = f"Upload {upload.id} or item {item_id} not found" - raise FossologyApiError(description, response) - else: - description = f"API error while getting clearing history for item {item_id} from upload {upload.uploadname}." - raise FossologyApiError(description, response) - - def get_prev_next( - self, upload: Upload, item_id: int, selection: PrevNextSelection | None = None - ) -> GetPrevNextItem: - """Get the index of the previous and the next time for an upload - - API Endpoint: GET /uploads/{id}/item/{itemId}/prev-next - - :param upload: the upload to get items from - :param item_id: the id of the item with clearing decision - :param selection: tell Fossology server how to select prev-next item - :type upload: Upload - :type item_id: int - :type selection: str - :return: list of items for the clearing history - :rtype: List[GetPrevNextItem] - :raises FossologyApiError: if the REST call failed - :raises AuthorizationError: if the REST call is not authorized - """ - params = {} - if selection: - params["selection"] = selection - - response = self.session.get( - f"{self.api}/uploads/{upload.id}/item/{item_id}/prev-next", params=params - ) - - if response.status_code == 200: - return GetPrevNextItem.from_json(response.json()) - - elif response.status_code == 404: - description = f"Upload {upload.id} or item {item_id} not found" - raise FossologyApiError(description, response) - else: - description = f"API error while getting prev-next items for {item_id} from upload {upload.uploadname}." - raise FossologyApiError(description, response) - - def get_bulk_history( - self, - upload: Upload, - item_id: int, - ) -> list[GetBulkHistory]: - """Get the bulk history for a specific upload item - - API Endpoint: GET /uploads/{id}/item/{itemId}/bulk-history - - :param upload: the upload to get items from - :param item_id: the id of the item with clearing decision - :type upload: Upload - :type item_id: int - :return: list of data from the bulk history - :rtype: List[GetBulkHistory] - :raises FossologyApiError: if the REST call failed - :raises AuthorizationError: if the REST call is not authorized - """ - response = self.session.get( - f"{self.api}/uploads/{upload.id}/item/{item_id}/bulk-history" - ) - - if response.status_code == 200: - bulk_history = [] - for item in response.json(): - bulk_history.append(GetBulkHistory.from_json(item)) - return bulk_history - - elif response.status_code == 404: - description = f"Upload {upload.id} or item {item_id} not found" - raise FossologyApiError(description, response) - else: - description = f"API error while getting bulk history for {item_id} from upload {upload.uploadname}." - raise FossologyApiError(description, response) - - def schedule_bulk_scan( - self, - upload: Upload, - item_id: int, - spec: dict, - ): - """Schedule a bulk scan for a specific upload item - - API Endpoint: POST /uploads/{id}/item/{itemId}/bulk-scan - - Bulk scan specifications `spec` are added to the request body, - following options are available: - - >>> bulk_scan_spec = { - ... "bulkActions": [ - ... { - ... "licenseShortName": 'MIT', - ... "licenseText": 'License text', - ... "acknowledgement": 'Acknowledgment text', - ... "comment": 'Comment text', - ... "licenseAction": 'ADD', # or 'REMOVE' - ... } - ... ], - ... "refText": 'Reference Text', - ... "bulkScope": 'folder', # or upload - ... "forceDecision": 'false', - ... "ignoreIrre": 'false', - ... "delimiters": 'DEFAULT', - ... "scanOnlyFindings": 'true', - ... } - - :param upload: the upload for the bulk scan - :param item_id: the id of the item for the bulk scan - :param spec: bulk scan specification - :type upload: Upload - :type item_id: int - :raises FossologyApiError: if the REST call failed - :raises AuthorizationError: if the REST call is not authorized - """ - headers = {"Content-Type": "application/json"} - response = self.session.post( - f"{self.api}/uploads/{upload.id}/item/{item_id}/bulk-scan", - headers=headers, - data=json.dumps(spec), - ) - if response.status_code == 201: - logger.info( - f"Bulk scan scheduled for upload {upload.uploadname}, item {item_id}" - ) - elif response.status_code == 400: - description = ( - f"Bad bulk scan request for upload {upload.id}, item {item_id}" - ) - raise FossologyApiError(description, response) - elif response.status_code == 404: - description = f"Upload {upload.id} or item {item_id} not found" - raise FossologyApiError(description, response) - else: - description = f"API error while scheduling bulk scan for item {item_id} from upload {upload.uploadname}." - raise FossologyApiError(description, response) diff --git a/tests/test_folders.py b/tests/test_folders.py index ab43408..34681e4 100644 --- a/tests/test_folders.py +++ b/tests/test_folders.py @@ -14,7 +14,7 @@ @responses.activate def test_list_folders_error(foss_server: str, foss: Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/folders", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/folders", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.list_folders() assert f"Unable to get a list of folders for {foss.user.name}" in str(excinfo.value) @@ -69,7 +69,7 @@ def test_create_folder_no_parent(foss: Fossology): def test_create_folder_returns_200_but_folder_does_not_exists( foss_server: str, foss: Fossology ): - responses.add(responses.POST, f"{foss_server}/api/v1/folders", status=200) + responses.add(responses.POST, f"{foss_server}/api/v2/folders", status=200) with pytest.raises(FossologyApiError) as excinfo: foss.create_folder(foss.rootFolder, "NoFolder") assert ( @@ -81,7 +81,7 @@ def test_create_folder_returns_200_but_folder_does_not_exists( @responses.activate def test_create_folder_error(foss_server: str, foss: Fossology): parent = Folder(secrets.randbelow(1000), "NonFolder", "", foss.rootFolder) - responses.add(responses.POST, f"{foss_server}/api/v1/folders", status=404) + responses.add(responses.POST, f"{foss_server}/api/v2/folders", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.create_folder(parent, "TestFolderNoParent") assert "Unable to create folder TestFolderNoParent" in str(excinfo.value) @@ -106,7 +106,7 @@ def test_update_folder(foss: Fossology): def test_update_folder_error(foss_server: str, foss: Fossology): folder = Folder(secrets.randbelow(1000), "Folder", "", foss.rootFolder) responses.add( - responses.PATCH, f"{foss_server}/api/v1/folders/{folder.id}", status=404 + responses.PATCH, f"{foss_server}/api/v2/folders/{folder.id}", status=404 ) with pytest.raises(FossologyApiError) as excinfo: foss.update_folder(folder) @@ -152,7 +152,7 @@ def test_copy_folder(foss: Fossology): def test_put_folder_error(foss_server: str, foss: Fossology): folder = Folder(secrets.randbelow(1000), "Folder", "", foss.rootFolder) responses.add( - responses.PUT, f"{foss_server}/api/v1/folders/{folder.id}", status=404 + responses.PUT, f"{foss_server}/api/v2/folders/{folder.id}", status=404 ) with pytest.raises(FossologyApiError) as excinfo: foss.move_folder(folder, foss.rootFolder) @@ -178,7 +178,7 @@ def test_delete_folder(foss: Fossology): def test_delete_folder_error(foss_server: str, foss: Fossology): folder = Folder(secrets.randbelow(1000), "Folder", "", foss.rootFolder) responses.add( - responses.DELETE, f"{foss_server}/api/v1/folders/{folder.id}", status=404 + responses.DELETE, f"{foss_server}/api/v2/folders/{folder.id}", status=404 ) with pytest.raises(FossologyApiError) as excinfo: foss.delete_folder(folder) diff --git a/tests/test_groups.py b/tests/test_groups.py index f16ba9b..dfe48ec 100644 --- a/tests/test_groups.py +++ b/tests/test_groups.py @@ -33,7 +33,7 @@ def verify_user_group_membership( # Test functions @responses.activate def test_list_groups_error(foss_server: str, foss: fossology.Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/groups", status=500) + responses.add(responses.GET, f"{foss_server}/api/v2/groups", status=500) with pytest.raises(FossologyApiError) as excinfo: foss.list_groups() assert f"Unable to get a list of groups for {foss.user.name}" in str(excinfo.value) @@ -41,7 +41,7 @@ def test_list_groups_error(foss_server: str, foss: fossology.Fossology): @responses.activate def test_list_group_members_error(foss_server: str, foss: fossology.Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/groups/42/members", status=500) + responses.add(responses.GET, f"{foss_server}/api/v2/groups/42/members", status=500) with pytest.raises(FossologyApiError) as excinfo: foss.list_group_members(42) assert "Unable to get a list of members for group 42" in str(excinfo.value) @@ -52,7 +52,7 @@ def test_delete_group_member_validation_error( foss_server: str, foss: fossology.Fossology ): responses.add( - responses.DELETE, f"{foss_server}/api/v1/groups/42/user/42", status=400 + responses.DELETE, f"{foss_server}/api/v2/groups/42/user/42", status=400 ) with pytest.raises(FossologyApiError) as excinfo: foss.delete_group_member(42, 42) @@ -64,7 +64,7 @@ def test_delete_group_member_validation_error( @responses.activate def test_delete_group_member_error(foss_server: str, foss: fossology.Fossology): responses.add( - responses.DELETE, f"{foss_server}/api/v1/groups/42/user/42", status=500 + responses.DELETE, f"{foss_server}/api/v2/groups/42/user/42", status=500 ) with pytest.raises(FossologyApiError) as excinfo: foss.delete_group_member(42, 42) @@ -77,7 +77,7 @@ def test_delete_group_member_error(foss_server: str, foss: fossology.Fossology): def test_delete_group_error(foss_server: str, foss: fossology.Fossology): group_id = secrets.randbelow(10) responses.add( - responses.DELETE, f"{foss_server}/api/v1/groups/{group_id}", status=500 + responses.DELETE, f"{foss_server}/api/v2/groups/{group_id}", status=500 ) with pytest.raises(FossologyApiError) as excinfo: foss.delete_group(group_id) diff --git a/tests/test_init.py b/tests/test_init.py index 3c26cd0..cf22e15 100644 --- a/tests/test_init.py +++ b/tests/test_init.py @@ -18,7 +18,7 @@ def test_get_info(foss: Fossology): def test_info_does_not_return_200(foss_server: str, foss: Fossology): responses.add( responses.GET, - f"{foss_server}/api/v1/info", + f"{foss_server}/api/v2/info", status=400, ) with pytest.raises(FossologyApiError) as excinfo: @@ -36,7 +36,7 @@ def test_get_health(foss: Fossology): def test_health_does_not_return_200(foss_server: str, foss: Fossology): responses.add( responses.GET, - f"{foss_server}/api/v1/health", + f"{foss_server}/api/v2/health", status=503, ) with pytest.raises(FossologyApiError) as excinfo: diff --git a/tests/test_upload_clearing.py b/tests/test_items.py similarity index 66% rename from tests/test_upload_clearing.py rename to tests/test_items.py index 1c2e434..dcd4149 100644 --- a/tests/test_upload_clearing.py +++ b/tests/test_items.py @@ -5,19 +5,81 @@ import responses from fossology import Fossology -from fossology.enums import PrevNextSelection +from fossology.enums import CopyrightStatus, PrevNextSelection from fossology.exceptions import FossologyApiError -from fossology.obj import Upload +from fossology.obj import FileInfo, Upload + + +def test_item_info(foss: Fossology, upload_with_jobs: Upload): + files, _ = foss.search(license="BSD") + info: FileInfo = foss.item_info(upload_with_jobs, files[0].uploadTreeId) + assert info.meta_info["fileUploadOrigin"] == "base-files_11.tar.xz" + + +def test_item_info_with_unknown_item_raises_api_error( + foss: Fossology, upload_with_jobs: Upload +): + with pytest.raises(FossologyApiError) as excinfo: + foss.item_info(upload_with_jobs, 1) + assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) + + +@responses.activate +def test_item_info_500_error( + foss: Fossology, foss_server: str, upload_with_jobs: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/info", + status=500, + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.item_info(upload_with_jobs, 1) + assert ( + f"API error while getting info for item 1 from upload {upload_with_jobs.uploadname}" + in excinfo.value.message + ) + + +def test_item_copyrights(foss: Fossology, upload_with_jobs: Upload): + files, _ = foss.search(license="BSD") + num_copyrights = foss.item_copyrights( + upload_with_jobs, files[0].uploadTreeId, CopyrightStatus.ACTIVE + ) + assert num_copyrights == 0 + + +def test_item_copyrights_with_unknown_item_raises_api_error( + foss: Fossology, upload_with_jobs: Upload +): + with pytest.raises(FossologyApiError) as excinfo: + foss.item_copyrights(upload_with_jobs, 1, CopyrightStatus.ACTIVE) + assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) + + +@responses.activate +def test_item_copyrights_500_error( + foss: Fossology, foss_server: str, upload_with_jobs: Upload +): + responses.add( + responses.GET, + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/totalcopyrights", + status=500, + ) + with pytest.raises(FossologyApiError) as excinfo: + foss.item_copyrights(upload_with_jobs, 1, CopyrightStatus.ACTIVE) + assert ( + f"API error while getting total copyrights for item 1 from upload {upload_with_jobs.uploadname}" + in excinfo.value.message + ) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_clearing_history(foss: Fossology, upload_with_jobs: Upload): files, _ = foss.search(license="BSD") history = foss.get_clearing_history(upload_with_jobs, files[0].uploadTreeId) assert not history -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_clearing_history_with_unknown_item_raises_api_error( foss: Fossology, upload_with_jobs: Upload ): @@ -26,14 +88,13 @@ def test_upload_get_clearing_history_with_unknown_item_raises_api_error( assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") @responses.activate def test_upload_get_clearing_history_500_error( foss: Fossology, foss_server: str, upload_with_jobs: Upload ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload_with_jobs.id}/item/1/clearing-history", + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/clearing-history", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -44,14 +105,12 @@ def test_upload_get_clearing_history_500_error( ) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_bulk_history(foss: Fossology, upload_with_jobs: Upload): files, _ = foss.search(license="BSD") history = foss.get_bulk_history(upload_with_jobs, files[0].uploadTreeId) assert not history -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_bulk_history_with_unknown_item_raises_api_error( foss: Fossology, upload_with_jobs: Upload ): @@ -60,14 +119,13 @@ def test_upload_get_bulk_history_with_unknown_item_raises_api_error( assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") @responses.activate def test_upload_get_bulk_history_500_error( foss: Fossology, foss_server: str, upload_with_jobs: Upload ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload_with_jobs.id}/item/1/clearing-history", + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/clearing-history", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -78,7 +136,6 @@ def test_upload_get_bulk_history_500_error( ) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_schedule_bulk_scan( foss: Fossology, upload_with_jobs: Upload, foss_bulk_scan_spec: dict ): @@ -92,7 +149,6 @@ def test_upload_schedule_bulk_scan( assert history[0].addedLicenses == ["MIT"] -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_schedule_bulk_scan_with_unknown_item_raises_api_error( foss: Fossology, upload_with_jobs: Upload, foss_bulk_scan_spec: dict ): @@ -101,7 +157,6 @@ def test_schedule_bulk_scan_with_unknown_item_raises_api_error( assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") @responses.activate def test_schedule_bulk_scan_500_error( foss: Fossology, @@ -111,7 +166,7 @@ def test_schedule_bulk_scan_500_error( ): responses.add( responses.POST, - f"{foss_server}/api/v1/uploads/{upload_with_jobs.id}/item/1/bulk-scan", + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/bulk-scan", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -122,14 +177,12 @@ def test_schedule_bulk_scan_500_error( ) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_prev_next(foss: Fossology, upload_with_jobs: Upload): files, _ = foss.search(license="BSD") prev_next = foss.get_prev_next(upload_with_jobs, files[0].uploadTreeId) assert prev_next -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_prev_next_with_licenses(foss: Fossology, upload_with_jobs: Upload): files, _ = foss.search(license="BSD") prev_next = foss.get_prev_next( @@ -138,7 +191,6 @@ def test_upload_get_prev_next_with_licenses(foss: Fossology, upload_with_jobs: U assert prev_next -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_prev_next_no_clearing(foss: Fossology, upload_with_jobs: Upload): files, _ = foss.search(license="BSD") prev_next = foss.get_prev_next( @@ -147,7 +199,6 @@ def test_upload_get_prev_next_no_clearing(foss: Fossology, upload_with_jobs: Upl assert prev_next -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") def test_upload_get_prev_next_with_unknown_item_raises_api_error( foss: Fossology, upload_with_jobs: Upload ): @@ -156,14 +207,13 @@ def test_upload_get_prev_next_with_unknown_item_raises_api_error( assert f"Upload {upload_with_jobs.id} or item 1 not found" in str(excinfo.value) -@pytest.mark.skip(reason="Not yet released, waiting for API version 1.6.0") @responses.activate def test_upload_get_prev_next_500_error( foss: Fossology, foss_server: str, upload_with_jobs: Upload ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload_with_jobs.id}/item/1/prev-next", + f"{foss_server}/api/v2/uploads/{upload_with_jobs.id}/item/1/prev-next", status=500, ) with pytest.raises(FossologyApiError) as excinfo: diff --git a/tests/test_jobs.py b/tests/test_jobs.py index 21cd7b4..b3b21dc 100644 --- a/tests/test_jobs.py +++ b/tests/test_jobs.py @@ -33,7 +33,7 @@ def test_schedule_jobs( assert job.name == upload_with_jobs.uploadname jobs, _ = foss.list_jobs(upload=upload_with_jobs) - assert len(jobs) == 3 + assert len(jobs) == 4 job = foss.detail_job(jobs[1].id, wait=True, timeout=30) assert job.status == JobStatus.COMPLETED.value @@ -61,7 +61,7 @@ def test_detail_job_wait_completed( @responses.activate def test_schedule_job_error(foss_server: str, foss: Fossology, upload: Upload): - responses.add(responses.POST, f"{foss_server}/api/v1/jobs", status=404) + responses.add(responses.POST, f"{foss_server}/api/v2/jobs", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.schedule_jobs(foss.rootFolder, upload, {}) assert f"Scheduling jobs for upload {upload.uploadname} failed" in str( @@ -71,7 +71,7 @@ def test_schedule_job_error(foss_server: str, foss: Fossology, upload: Upload): @responses.activate def test_list_jobs_error(foss_server: str, foss: Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/jobs", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/jobs", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.list_jobs() assert "Unable to retrieve the list of jobs from page 1" in str(excinfo.value) @@ -79,7 +79,7 @@ def test_list_jobs_error(foss_server: str, foss: Fossology): @responses.activate def test_list_all_jobs_access_denied(foss_server: str, foss: Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/jobs/all", status=403) + responses.add(responses.GET, f"{foss_server}/api/v2/jobs/all", status=403) with pytest.raises(FossologyApiError) as excinfo: foss.list_jobs(all=True) assert "Access denied to /jobs/all endpoint" in str(excinfo.value) @@ -88,8 +88,8 @@ def test_list_all_jobs_access_denied(foss_server: str, foss: Fossology): @responses.activate def test_detail_job_error(foss_server: str, foss: Fossology): job_id = secrets.randbelow(1000) - responses.add(responses.GET, f"{foss_server}/api/v1/jobs/{job_id}", status=404) - responses.add(responses.GET, f"{foss_server}/api/v1/jobs/{job_id}", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/jobs/{job_id}", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/jobs/{job_id}", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.detail_job(job_id, wait=True) assert f"Error while getting details for job {job_id}" in str(excinfo.value) @@ -102,16 +102,16 @@ def test_paginated_list_jobs(foss: Fossology, upload_with_jobs: Upload): jobs, total_pages = foss.list_jobs( upload=upload_with_jobs, page_size=1, all_pages=True ) - assert len(jobs) == 3 - assert total_pages == 3 + assert len(jobs) == 4 + assert total_pages == 4 jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=1, page=1) assert len(jobs) == 1 - assert total_pages == 3 + assert total_pages == 4 jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=1, page=2) assert len(jobs) == 1 - assert total_pages == 3 + assert total_pages == 4 jobs, total_pages = foss.list_jobs(upload=upload_with_jobs, page_size=2, page=1) assert len(jobs) == 2 diff --git a/tests/test_license.py b/tests/test_license.py index c74b96a..5d54f85 100644 --- a/tests/test_license.py +++ b/tests/test_license.py @@ -34,7 +34,7 @@ def test_another_license(): @responses.activate def test_detail_license_error(foss_server: str, foss: fossology.Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/license/Blah", status=500) + responses.add(responses.GET, f"{foss_server}/api/v2/license/Blah", status=500) with pytest.raises(FossologyApiError) as excinfo: foss.detail_license("Blah") assert "Error while getting license Blah" in str(excinfo.value) @@ -48,7 +48,7 @@ def test_detail_license_not_found(foss: fossology.Fossology): @responses.activate def test_list_licenses_error(foss_server: str, foss: fossology.Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/license", status=500) + responses.add(responses.GET, f"{foss_server}/api/v2/license", status=500) with pytest.raises(FossologyApiError) as excinfo: foss.list_licenses() assert "Unable to retrieve the list of licenses from page 1" in str(excinfo.value) @@ -76,7 +76,7 @@ def test_get_all_candidate_licenses(foss: fossology.Fossology): def test_add_license_error( foss_server: str, foss: fossology.Fossology, test_license: License ): - responses.add(responses.POST, f"{foss_server}/api/v1/license", status=500) + responses.add(responses.POST, f"{foss_server}/api/v2/license", status=500) with pytest.raises(FossologyApiError) as excinfo: foss.add_license(test_license) assert f"Error while adding new license {test_license.shortName}" in str( @@ -93,7 +93,7 @@ def test_add_license_already_exists( ): mocked_logger = MagicMock() monkeypatch.setattr("fossology.license.logger", mocked_logger) - responses.add(responses.POST, f"{foss_server}/api/v1/license", status=409) + responses.add(responses.POST, f"{foss_server}/api/v2/license", status=409) foss.add_license(test_license) mocked_logger.info.assert_called_once() @@ -125,7 +125,7 @@ def test_patch_license_error( foss_server: str, foss: fossology.Fossology, test_license: License ): responses.add( - responses.PATCH, f"{foss_server}/api/v1/license/License-1.0", status=500 + responses.PATCH, f"{foss_server}/api/v2/license/License-1.0", status=500 ) with pytest.raises(FossologyApiError) as excinfo: foss.update_license(test_license.shortName) diff --git a/tests/test_report.py b/tests/test_report.py index b3a25ad..2ec7022 100644 --- a/tests/test_report.py +++ b/tests/test_report.py @@ -51,11 +51,11 @@ def test_generate_report(foss: Fossology, upload: Upload): def test_report_error(foss_server: str, foss: Fossology, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/report", + f"{foss_server}/api/v2/report", status=503, headers={"Retry-After": "1"}, ) - responses.add(responses.GET, f"{foss_server}/api/v1/report", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/report", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.generate_report(upload) assert f"Report generation for upload {upload.uploadname} failed" in str( @@ -68,7 +68,7 @@ def test_download_report_error(foss_server: str, foss: Fossology): report_id = secrets.randbelow(1000) responses.add( responses.GET, - f"{foss_server}/api/v1/report/{report_id}", + f"{foss_server}/api/v2/report/{report_id}", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -81,7 +81,7 @@ def test_download_report_filename_without_quotes(foss_server: str, foss: Fossolo report_id = "1" responses.add( responses.GET, - f"{foss_server}/api/v1/report/{report_id}", + f"{foss_server}/api/v2/report/{report_id}", status=200, headers={"Content-Disposition": "attachment; filename=Report_FileName.docx"}, ) @@ -94,7 +94,7 @@ def test_download_report_filename_with_quotes(foss_server: str, foss: Fossology) report_id = "1" responses.add( responses.GET, - f"{foss_server}/api/v1/report/{report_id}", + f"{foss_server}/api/v2/report/{report_id}", status=200, headers={"Content-Disposition": 'attachment; filename="Report_FileName.docx"'}, ) @@ -107,7 +107,7 @@ def test_download_report_filename_with_single_quotes(foss_server: str, foss: Fos report_id = "1" responses.add( responses.GET, - f"{foss_server}/api/v1/report/{report_id}", + f"{foss_server}/api/v2/report/{report_id}", status=200, headers={"Content-Disposition": "attachment; filename='Report_FileName.docx'"}, ) diff --git a/tests/test_search.py b/tests/test_search.py index 4d3fdc7..182061f 100644 --- a/tests/test_search.py +++ b/tests/test_search.py @@ -12,29 +12,19 @@ from fossology.obj import Upload -# See: https://github.com/fossology/fossology/pull/2390 -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search_nogroup(foss: Fossology): with pytest.raises(FossologyApiError) as excinfo: foss.search(searchType=SearchTypes.ALLFILES, filename="GPL%", group="test") - assert "Searching for group test not authorized" in str(excinfo.value) + assert "Unable to get a result with the given search criteria" in str(excinfo.value) -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search(foss: Fossology, upload: Upload): - search_result = foss.search(searchType=SearchTypes.ALLFILES, filename="GPL%") + search_result, _ = foss.search(searchType=SearchTypes.ALLFILES, filename="GPL%") assert search_result -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search_nothing_found(foss: Fossology, upload: Upload): - search_result = foss.search( + search_result, _ = foss.search( searchType=SearchTypes.ALLFILES, filename="test%", tag="test", @@ -46,22 +36,16 @@ def test_search_nothing_found(foss: Fossology, upload: Upload): assert search_result == [] -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search_directory(foss: Fossology, upload: Upload): - search_result = foss.search( - searchType=SearchTypes.DIRECTORIES, + search_result, _ = foss.search( + searchType=SearchTypes.DIRECTORY, filename="share", ) - assert search_result + assert not search_result -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search_upload(foss: Fossology, upload: Upload): - search_result = foss.search( + search_result, _ = foss.search( searchType=SearchTypes.ALLFILES, upload=upload, filename="share", @@ -69,9 +53,6 @@ def test_search_upload(foss: Fossology, upload: Upload): assert search_result -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) def test_search_upload_does_not_exist(foss: Fossology): hash = {"sha1": "", "md5": "", "sha256": "", "size": ""} fake_upload = Upload( @@ -83,7 +64,7 @@ def test_search_upload_does_not_exist(foss: Fossology): "2020-12-30", hash=hash, ) - search_result = foss.search( + search_result, _ = foss.search( searchType=SearchTypes.ALLFILES, upload=fake_upload, filename="share", @@ -91,12 +72,9 @@ def test_search_upload_does_not_exist(foss: Fossology): assert not search_result -@pytest.mark.skip( - reason="current Fossology version has a bug, /search is not supported, fixed in 4.3.0" -) @responses.activate def test_search_error(foss_server: str, foss: Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/search", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/search", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.search() assert "Unable to get a result with the given search criteria" in str(excinfo.value) @@ -130,7 +108,7 @@ def test_filesearch_nogroup(foss: Fossology): @responses.activate def test_filesearch_error(foss_server: str, foss: Fossology): - responses.add(responses.POST, f"{foss_server}/api/v1/filesearch", status=404) + responses.add(responses.POST, f"{foss_server}/api/v2/filesearch", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.filesearch() assert "Unable to get a result with the given filesearch criteria" in str( diff --git a/tests/test_upload_licenses_copyrights.py b/tests/test_upload_licenses_copyrights.py index afdcc32..6e019ec 100644 --- a/tests/test_upload_licenses_copyrights.py +++ b/tests/test_upload_licenses_copyrights.py @@ -13,12 +13,12 @@ def test_upload_licenses(foss: Fossology, upload_with_jobs: Upload): # Default agent "nomos" licenses = foss.upload_licenses(upload_with_jobs) - assert len(licenses) == 56 + assert len(licenses) == 50 def test_upload_licenses_with_containers(foss: Fossology, upload_with_jobs: Upload): licenses = foss.upload_licenses(upload_with_jobs, containers=True) - assert len(licenses) == 56 + assert len(licenses) == 50 def test_upload_licenses_agent_ojo(foss: Fossology, upload_with_jobs: Upload): @@ -33,7 +33,7 @@ def test_upload_licenses_agent_monk(foss: Fossology, upload_with_jobs: Upload): def test_upload_licenses_and_copyrights(foss: Fossology, upload_with_jobs: Upload): licenses = foss.upload_licenses(upload_with_jobs, copyright=True) - assert len(licenses) == 56 + assert len(licenses) == 50 def test_upload_licenses_with_unknown_group_raises_authorization_error( @@ -51,7 +51,7 @@ def test_upload_licenses_with_unknown_group_raises_authorization_error( def test_upload_licenses_412_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/licenses", + f"{foss_server}/api/v2/uploads/{upload.id}/licenses", status=412, ) with pytest.raises(FossologyApiError) as excinfo: @@ -66,7 +66,7 @@ def test_upload_licenses_412_error(foss: Fossology, foss_server: str, upload: Up def test_upload_licenses_503_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/licenses", + f"{foss_server}/api/v2/uploads/{upload.id}/licenses", status=503, ) with pytest.raises(RetryError): @@ -77,7 +77,7 @@ def test_upload_licenses_503_error(foss: Fossology, foss_server: str, upload: Up def test_upload_licenses_500_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/licenses", + f"{foss_server}/api/v2/uploads/{upload.id}/licenses", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -97,7 +97,7 @@ def test_upload_copyrights(foss: Fossology, upload_with_jobs: Upload): def test_upload_copyrights_403_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/copyrights", + f"{foss_server}/api/v2/uploads/{upload.id}/copyrights", status=403, ) with pytest.raises(AuthorizationError) as excinfo: @@ -112,7 +112,7 @@ def test_upload_copyrights_403_error(foss: Fossology, foss_server: str, upload: def test_upload_copyrights_412_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/copyrights", + f"{foss_server}/api/v2/uploads/{upload.id}/copyrights", status=412, ) with pytest.raises(FossologyApiError) as excinfo: @@ -127,7 +127,7 @@ def test_upload_copyrights_412_error(foss: Fossology, foss_server: str, upload: def test_upload_copyrights_503_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/copyrights", + f"{foss_server}/api/v2/uploads/{upload.id}/copyrights", status=503, ) with pytest.raises(RetryError): @@ -138,7 +138,7 @@ def test_upload_copyrights_503_error(foss: Fossology, foss_server: str, upload: def test_upload_copyrights_500_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/copyrights", + f"{foss_server}/api/v2/uploads/{upload.id}/copyrights", status=500, ) with pytest.raises(FossologyApiError) as excinfo: diff --git a/tests/test_upload_permissions.py b/tests/test_upload_permissions.py index f42d322..1b2f5f5 100644 --- a/tests/test_upload_permissions.py +++ b/tests/test_upload_permissions.py @@ -58,7 +58,7 @@ def test_get_upload_permissions_if_api_returns_403_raises_authorization_error( ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/perm-groups", + f"{foss_server}/api/v2/uploads/{upload.id}/perm-groups", status=403, ) with pytest.raises(AuthorizationError) as excinfo: @@ -74,7 +74,7 @@ def test_get_upload_permissions_if_api_returns_500_raises_fossology_error( ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/perm-groups", + f"{foss_server}/api/v2/uploads/{upload.id}/perm-groups", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -108,7 +108,7 @@ def test_change_upload_permissions_if_api_returns_400_raises_fossology_error( ): responses.add( responses.PUT, - f"{foss_server}/api/v1/uploads/{upload.id}/permissions", + f"{foss_server}/api/v2/uploads/{upload.id}/permissions", status=400, ) with pytest.raises(FossologyApiError) as excinfo: @@ -124,7 +124,7 @@ def test_change_upload_permissions_if_api_returns_403_raises_authorization_error ): responses.add( responses.PUT, - f"{foss_server}/api/v1/uploads/{upload.id}/permissions", + f"{foss_server}/api/v2/uploads/{upload.id}/permissions", status=403, ) with pytest.raises(AuthorizationError) as excinfo: @@ -140,7 +140,7 @@ def test_change_upload_permissions_if_api_returns_500_raises_fossology_error( ): responses.add( responses.PUT, - f"{foss_server}/api/v1/uploads/{upload.id}/permissions", + f"{foss_server}/api/v2/uploads/{upload.id}/permissions", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -157,7 +157,7 @@ def test_change_upload_permissions_if_api_returns_503_raises_fossology_error( ): responses.add( responses.PUT, - f"{foss_server}/api/v1/uploads/{upload.id}/permissions", + f"{foss_server}/api/v2/uploads/{upload.id}/permissions", status=503, ) with pytest.raises(FossologyApiError) as excinfo: diff --git a/tests/test_uploads.py b/tests/test_uploads.py index 0414458..b63ad33 100644 --- a/tests/test_uploads.py +++ b/tests/test_uploads.py @@ -47,7 +47,7 @@ def test_get_upload_error(foss: Fossology, foss_server: str): upload_id = 100 responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload_id}", + f"{foss_server}/api/v2/uploads/{upload_id}", status=500, ) with pytest.raises(FossologyApiError) as excinfo: @@ -120,7 +120,7 @@ def test_empty_upload(foss: Fossology): def test_upload_error(foss: Fossology, foss_server: str, test_file_path: str): responses.add( responses.POST, - f"{foss_server}/api/v1/uploads", + f"{foss_server}/api/v2/uploads", status=500, ) description = "Test upload API error" @@ -159,7 +159,7 @@ def test_move_upload_to_non_existing_folder(foss: Fossology, upload: Upload): def test_move_upload_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.PUT, - f"{foss_server}/api/v1/uploads/{upload.id}", + f"{foss_server}/api/v2/uploads/{upload.id}", status=500, ) with pytest.raises(FossologyApiError): @@ -183,7 +183,7 @@ def test_update_upload_with_unknown_group_raises_error(foss: Fossology, upload: def test_update_upload_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.PATCH, - f"{foss_server}/api/v1/uploads/{upload.id}", + f"{foss_server}/api/v2/uploads/{upload.id}", status=500, ) with pytest.raises(FossologyApiError): @@ -204,7 +204,7 @@ def test_upload_summary(foss: Fossology, upload: Upload): def test_upload_summary_500_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/summary", + f"{foss_server}/api/v2/uploads/{upload.id}/summary", status=500, ) with pytest.raises(FossologyApiError): @@ -275,7 +275,7 @@ def test_paginated_list_uploads(foss: Fossology, upload: Upload, test_file_path: def test_list_uploads_500_error(foss: Fossology, foss_server: str, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads", + f"{foss_server}/api/v2/uploads", status=500, ) with pytest.raises(FossologyApiError): @@ -301,7 +301,7 @@ def test_download_upload_authorization_error( ): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/download", + f"{foss_server}/api/v2/uploads/{upload.id}/download", status=403, ) with pytest.raises(AuthorizationError) as excinfo: @@ -313,7 +313,7 @@ def test_download_upload_authorization_error( def test_download_upload_error(foss_server: str, foss: Fossology, upload: Upload): responses.add( responses.GET, - f"{foss_server}/api/v1/uploads/{upload.id}/download", + f"{foss_server}/api/v2/uploads/{upload.id}/download", status=401, ) with pytest.raises(FossologyApiError) as excinfo: diff --git a/tests/test_users.py b/tests/test_users.py index 2c6a044..359285e 100644 --- a/tests/test_users.py +++ b/tests/test_users.py @@ -88,6 +88,8 @@ def test_unknown_user(foss: Fossology): def test_list_users(foss: Fossology): # Fixture created_foss_user creates a new user for the test session + # If the whole test suite runs, a second user is created + # Running this test only will result in 1 user users = foss.list_users() assert len(users) == 2 @@ -96,7 +98,7 @@ def test_list_users(foss: Fossology): def test_get_self_error(foss_server: str, foss: Fossology): responses.add( responses.GET, - f"{foss_server}/api/v1/users/self", + f"{foss_server}/api/v2/users/self", status=500, ) with pytest.raises(FossologyApiError): @@ -109,7 +111,7 @@ def test_get_self_with_agents( ): user = foss_user responses.add( - responses.GET, f"{foss_server}/api/v1/users/self", status=200, json=user + responses.GET, f"{foss_server}/api/v2/users/self", status=200, json=user ) user_from_api = foss.get_self() assert user_from_api.agents.to_dict() == foss_user_agents @@ -121,7 +123,7 @@ def test_detail_user_with_agents( ): user = foss_user responses.add( - responses.GET, f"{foss_server}/api/v1/users/{user['id']}", status=200, json=user + responses.GET, f"{foss_server}/api/v2/users/{user['id']}", status=200, json=user ) user_from_api = foss.detail_user(user["id"]) assert user_from_api.agents.to_dict() == foss_user_agents @@ -132,14 +134,14 @@ def test_list_users_with_agents( foss_server: str, foss: Fossology, foss_user: dict, foss_user_agents: dict ): users = [foss_user] - responses.add(responses.GET, f"{foss_server}/api/v1/users", status=200, json=users) + responses.add(responses.GET, f"{foss_server}/api/v2/users", status=200, json=users) users_from_api = foss.list_users() assert users_from_api[0].agents.to_dict() == foss_user_agents @responses.activate def test_list_users_error(foss_server: str, foss: Fossology): - responses.add(responses.GET, f"{foss_server}/api/v1/users", status=404) + responses.add(responses.GET, f"{foss_server}/api/v2/users", status=404) with pytest.raises(FossologyApiError) as excinfo: foss.list_users() assert f"Unable to get a list of users from {foss_server}" in str(excinfo.value) @@ -156,8 +158,8 @@ def test_detail_user(foss: Fossology): @responses.activate def test_delete_user(foss_server: str, foss: Fossology): user = Mock(name="Test User", id=secrets.randbelow(1000)) - responses.add(responses.DELETE, f"{foss_server}/api/v1/users/{user.id}", status=202) - responses.add(responses.DELETE, f"{foss_server}/api/v1/users/{user.id}", status=404) + responses.add(responses.DELETE, f"{foss_server}/api/v2/users/{user.id}", status=202) + responses.add(responses.DELETE, f"{foss_server}/api/v2/users/{user.id}", status=404) assert not foss.delete_user(user) with pytest.raises(FossologyApiError) as excinfo: foss.delete_user(user)