Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Chore/3.2.1 #130

Merged
merged 4 commits into from
Apr 4, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/workflows/fossologytests.yml
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,7 @@ on:

jobs:
test-latest:
name: Integration Tests (latest Fossology - 4.4.0-rc2)
name: Integration Tests (Fossology - Latest)
runs-on: ubuntu-latest

container:
Expand All @@ -20,7 +20,7 @@ jobs:

services:
fossology:
image: fossology/fossology:4.4.0-rc2
image: fossology/fossology:latest
ports:
- 8081:80
volumes:
Expand Down
12 changes: 6 additions & 6 deletions README.rst
Original file line number Diff line number Diff line change
Expand Up @@ -26,13 +26,13 @@ A simple wrapper for the Fossology REST API.

See `the OpenAPI specification <https://raw.githubusercontent.com/fossology/fossology/master/src/www/ui/api/documentation/openapi.yaml>`_ used to implement this library.

Current release is compatible with **Fossology version 4.4.0-rc2** - API version 2.0.0 (not all endpoints are supported)
Current release is compatible with **Fossology version 4.4.0** - API version 1.6.1 (not all endpoints are supported)

`See release notes <https://github.com/fossology/fossology-python/releases>`_ for all details.

If you miss an API Endpoint, please open a new issue or contribute a pull request.

API v1 is supported too, it needs to be specified explicitly.
API v2 is partially supported too, however the specification is not stable yet and not all endpoints are supported.

Documentation
=============
Expand Down Expand Up @@ -68,14 +68,14 @@ Using the API
FOSSOLOGY_PASSWORD = "fossy"
TOKEN_NAME = "fossy_token"

# By default version v2 of the token generation API will be used
# By default version v1 of the token generation API will be used
token = fossology_token(
FOSSOLOGY_SERVER,
FOSSOLOGY_USER,
FOSSOLOGY_PASSWORD,
TOKEN_NAME,
TokenScope.WRITE
version="v2"
version="v1"
)

- Start using the API:
Expand All @@ -84,8 +84,8 @@ Using the API

from fossology import Fossology

# By default version v2 of the API will be used
foss = Fossology(FOSSOLOGY_SERVER, token, FOSSOLOGY_USER, version="v2")
# By default version v1 of the API will be used
foss = Fossology(FOSSOLOGY_SERVER, token, FOSSOLOGY_USER, version="v1")
print(f"Logged in as user {foss.user.name}")


Expand Down
2 changes: 1 addition & 1 deletion docs-source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,7 @@
copyright = "2021, Siemens AG"

# The full version, including major/minor/patch tags
release = "3.2.0"
release = "3.2.1"


# -- General configuration ---------------------------------------------------
Expand Down
10 changes: 5 additions & 5 deletions fossology/__init__.py
Original file line number Diff line number Diff line change
Expand Up @@ -31,7 +31,7 @@ def fossology_token(
token_name,
token_scope=TokenScope.READ,
token_expire=None,
version="v2",
version="v1",
):
"""Generate an API token using username/password

Expand All @@ -41,7 +41,7 @@ def fossology_token(

>>> from fossology import fossology_token # doctest: +SKIP
>>> from fossology.obj import TokenScope # doctest: +SKIP
>>> token = fossology_token("https://fossology.example.com/repo", "Me", "MyPassword", "MyToken", version="v2") # doctest: +SKIP
>>> token = fossology_token("https://fossology.example.com/repo", "Me", "MyPassword", "MyToken", version="v1") # doctest: +SKIP


:param url: the URL of the Fossology server
Expand All @@ -50,7 +50,7 @@ def fossology_token(
:param name: the name of the token
:param scope: the scope of the token (default: TokenScope.READ)
:param expire: the expire date of the token, e.g. 2019-12-25 (default: max. 30 days)
:param version: the version of the API to use (default: "v2")
:param version: the version of the API to use (default: "v1")
:type url: string
:type username: string
:type password: string
Expand Down Expand Up @@ -118,15 +118,15 @@ class Fossology(

:param url: URL of the Fossology instance
:param token: The API token generated using the Fossology UI
:param version: the version of the API to use (default: "v2")
:param version: the version of the API to use (default: "v1")
:type url: str
:type token: str
:type version: str
:raises FossologyApiError: if a REST call failed
:raises AuthenticationError: if the user couldn't be authenticated
"""

def __init__(self, url, token, version="v2"):
def __init__(self, url, token, version="v1"):
self.host = url
self.token = token
self.users = list()
Expand Down
55 changes: 34 additions & 21 deletions fossology/uploads.py
Original file line number Diff line number Diff line change
Expand Up @@ -156,7 +156,7 @@ def upload_file(

>>> from fossology import Fossology
>>> from fossology.enums import AccessLevel
>>> foss = Fossology(FOSS_URL, FOSS_TOKEN, username) # doctest: +SKIP
>>> foss = Fossology(FOSS_URL, FOSS_TOKEN) # doctest: +SKIP
>>> my_upload = foss.upload_file(
... foss.rootFolder,
... file="my-package.zip",
Expand Down Expand Up @@ -237,39 +237,52 @@ def upload_file(
:raises FossologyApiError: if the REST call failed
:raises AuthorizationError: if the REST call is not authorized
"""
headers = {"folderId": str(folder.id)}
if description:
headers["uploadDescription"] = description
if access_level:
headers["public"] = access_level.value
if apply_global:
headers["applyGlobal"] = "true"
if ignore_scm:
headers["ignoreScm"] = "true"
if group:
data: dict = {
"folderId": str(folder.id),
"uploadDescription": description,
"public": access_level.value
if access_level
else AccessLevel.PROTECTED.value,
"applyGlobal": apply_global,
"ignoreScm": ignore_scm,
"uploadType": "file",
}

headers = {}
if "v1" in self.api:
headers = {
k: str(v).lower() if isinstance(v, bool) else v for k, v in data.items()
} # Needed for API v1.x
headers["groupName"] = group
endpoint = f"{self.api}/uploads"
else:
if group:
endpoint = f"{self.api}/uploads?groupName={group}"
else:
endpoint = f"{self.api}/uploads"

if file:
headers["uploadType"] = "file"
data["uploadType"] = headers["uploadType"] = "file"
with open(file, "rb") as fp:
files = {"fileInput": fp}
response = self.session.post(
f"{self.api}/uploads", files=files, headers=headers
endpoint, files=files, headers=headers, data=data
)
elif vcs or url or server:
data = dict
if vcs:
headers["uploadType"] = "vcs"
data = {"location": vcs} # type: ignore
data["location"] = vcs # type: ignore
data["uploadType"] = headers["uploadType"] = "vcs"
elif url:
headers["uploadType"] = "url"
data = {"location": url} # type: ignore
data["location"] = url # type: ignore
data["uploadType"] = headers["uploadType"] = "url"
elif server:
headers["uploadType"] = "server"
data = {"location": server} # type: ignore
data["location"] = server # type: ignore
data["uploadType"] = headers["uploadType"] = "server"
headers["Content-Type"] = "application/json"
response = self.session.post(
f"{self.api}/uploads", data=json.dumps(data), headers=headers
endpoint,
data=json.dumps(data),
headers=headers,
)
else:
logger.info(
Expand Down
2 changes: 1 addition & 1 deletion pyproject.toml
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[tool.poetry]
name = "fossology"
version = "3.2.0"
version = "3.2.1"
description = "A library to automate Fossology from Python scripts"
authors = ["Marion Deveaud <[email protected]>"]
license = "MIT License"
Expand Down
16 changes: 8 additions & 8 deletions tests/conftest.py
Original file line number Diff line number Diff line change
Expand Up @@ -175,11 +175,11 @@ def foss(foss_server: str, foss_token: str, foss_agents: Agents) -> fossology.Fo


@pytest.fixture(scope="session")
def foss_v1(
def foss_v2(
foss_server: str, foss_token: str, foss_agents: Agents
) -> fossology.Fossology:
try:
foss = fossology.Fossology(foss_server, foss_token, version="v1")
foss = fossology.Fossology(foss_server, foss_token, version="v2")
except (FossologyApiError, AuthenticationError) as error:
exit(error.message)

Expand Down Expand Up @@ -231,20 +231,20 @@ def upload(


@pytest.fixture(scope="function")
def upload_v1(
foss_v1: fossology.Fossology,
def upload_v2(
foss_v2: fossology.Fossology,
test_file_path: str,
) -> Generator:
upload = foss_v1.upload_file(
foss_v1.rootFolder,
upload = foss_v2.upload_file(
foss_v2.rootFolder,
file=test_file_path,
description="Test upload via fossology-python lib",
access_level=AccessLevel.PUBLIC,
wait_time=5,
)
jobs_lookup(foss_v1, upload)
jobs_lookup(foss_v2, upload)
yield upload
foss_v1.delete_upload(upload)
foss_v2.delete_upload(upload)
time.sleep(5)


Expand Down
12 changes: 6 additions & 6 deletions tests/test_folders.py
Original file line number Diff line number Diff line change
Expand Up @@ -14,7 +14,7 @@

@responses.activate
def test_list_folders_error(foss_server: str, foss: Fossology):
responses.add(responses.GET, f"{foss_server}/api/v2/folders", status=404)
responses.add(responses.GET, f"{foss_server}/api/v1/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)
Expand Down Expand Up @@ -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/v2/folders", status=200)
responses.add(responses.POST, f"{foss_server}/api/v1/folders", status=200)
with pytest.raises(FossologyApiError) as excinfo:
foss.create_folder(foss.rootFolder, "NoFolder")
assert (
Expand All @@ -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/v2/folders", status=404)
responses.add(responses.POST, f"{foss_server}/api/v1/folders", status=404)
with pytest.raises(FossologyApiError) as excinfo:
foss.create_folder(parent, "TestFolderNoParent")
assert "Unable to create folder TestFolderNoParent" in str(excinfo.value)
Expand All @@ -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/v2/folders/{folder.id}", status=404
responses.PATCH, f"{foss_server}/api/v1/folders/{folder.id}", status=404
)
with pytest.raises(FossologyApiError) as excinfo:
foss.update_folder(folder)
Expand Down Expand Up @@ -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/v2/folders/{folder.id}", status=404
responses.PUT, f"{foss_server}/api/v1/folders/{folder.id}", status=404
)
with pytest.raises(FossologyApiError) as excinfo:
foss.move_folder(folder, foss.rootFolder)
Expand All @@ -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/v2/folders/{folder.id}", status=404
responses.DELETE, f"{foss_server}/api/v1/folders/{folder.id}", status=404
)
with pytest.raises(FossologyApiError) as excinfo:
foss.delete_folder(folder)
Expand Down
10 changes: 5 additions & 5 deletions tests/test_groups.py
Original file line number Diff line number Diff line change
Expand Up @@ -33,15 +33,15 @@ 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/v2/groups", status=500)
responses.add(responses.GET, f"{foss_server}/api/v1/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)


@responses.activate
def test_list_group_members_error(foss_server: str, foss: fossology.Fossology):
responses.add(responses.GET, f"{foss_server}/api/v2/groups/42/members", status=500)
responses.add(responses.GET, f"{foss_server}/api/v1/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)
Expand All @@ -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/v2/groups/42/user/42", status=400
responses.DELETE, f"{foss_server}/api/v1/groups/42/user/42", status=400
)
with pytest.raises(FossologyApiError) as excinfo:
foss.delete_group_member(42, 42)
Expand All @@ -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/v2/groups/42/user/42", status=500
responses.DELETE, f"{foss_server}/api/v1/groups/42/user/42", status=500
)
with pytest.raises(FossologyApiError) as excinfo:
foss.delete_group_member(42, 42)
Expand All @@ -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/v2/groups/{group_id}", status=500
responses.DELETE, f"{foss_server}/api/v1/groups/{group_id}", status=500
)
with pytest.raises(FossologyApiError) as excinfo:
foss.delete_group(group_id)
Expand Down
28 changes: 26 additions & 2 deletions tests/test_init.py
Original file line number Diff line number Diff line change
Expand Up @@ -15,12 +15,24 @@ def test_get_info(foss: Fossology):


@responses.activate
def test_info_does_not_return_200(foss_server: str, foss: Fossology):
def test_info_v2_does_not_return_200(foss_server: str, foss_v2: Fossology):
responses.add(
responses.GET,
f"{foss_server}/api/v2/info",
status=400,
)
with pytest.raises(FossologyApiError) as excinfo:
foss_v2.get_info()
assert "Error while getting API info" in str(excinfo.value)


@responses.activate
def test_info_does_not_return_200(foss_server: str, foss: Fossology):
responses.add(
responses.GET,
f"{foss_server}/api/v1/info",
status=400,
)
with pytest.raises(FossologyApiError) as excinfo:
foss.get_info()
assert "Error while getting API info" in str(excinfo.value)
Expand All @@ -36,9 +48,21 @@ 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/v2/health",
f"{foss_server}/api/v1/health",
status=503,
)
with pytest.raises(FossologyApiError) as excinfo:
foss.get_health()
assert "Error while getting health info" in str(excinfo.value)


@responses.activate
def test_health_v2_does_not_return_200(foss_server: str, foss_v2: Fossology):
responses.add(
responses.GET,
f"{foss_server}/api/v2/health",
status=503,
)
with pytest.raises(FossologyApiError) as excinfo:
foss_v2.get_health()
assert "Error while getting health info" in str(excinfo.value)
Loading