Skip to content

Commit

Permalink
refactor(0.2.0): get report name from HTTP header
Browse files Browse the repository at this point in the history
Interface change for `download_report`:
- only the report id is accepted as parameter
- removed `as_zip` option, Fossology only returns uncompressed
reports
- return a tuple of the report content and the file name as
returned by the HTTP GET reponse header
- use typehints and fix exceptions descriptions
  • Loading branch information
deveaud-m committed Oct 16, 2020
1 parent 9f4b265 commit 04ca22d
Show file tree
Hide file tree
Showing 4 changed files with 26 additions and 44 deletions.
4 changes: 2 additions & 2 deletions docs-source/conf.py
Original file line number Diff line number Diff line change
Expand Up @@ -22,8 +22,8 @@
project = "fossology"
copyright = "2020, Siemens AG"

# The full version, including alpha/beta/rc tags
release = "0.1.4"
# The full version, including major/minor/patch tags
release = "0.2.0"


# -- General configuration ---------------------------------------------------
Expand Down
31 changes: 16 additions & 15 deletions fossology/report.py
Original file line number Diff line number Diff line change
Expand Up @@ -4,8 +4,10 @@
import re
import time
import logging
from typing import Tuple

from tenacity import retry, TryAgain, stop_after_attempt, retry_if_exception_type
from .obj import ReportFormat, Upload
from .exceptions import FossologyApiError

logger = logging.getLogger(__name__)
Expand All @@ -16,7 +18,7 @@ class Report:
"""Class dedicated to all "report" related endpoints"""

@retry(retry=retry_if_exception_type(TryAgain), stop=stop_after_attempt(3))
def generate_report(self, upload, report_format=None):
def generate_report(self, upload: Upload, report_format: ReportFormat = None):
"""Generate a report for a given upload
API Endpoint: GET /report
Expand Down Expand Up @@ -45,11 +47,11 @@ def generate_report(self, upload, report_format=None):
time.sleep(int(wait_time))
raise TryAgain
else:
description = f"Report generation for upload {upload.name} failed"
description = f"Report generation for upload {upload.uploadname} failed"
raise FossologyApiError(description, response)

@retry(retry=retry_if_exception_type(TryAgain), stop=stop_after_attempt(3))
def download_report(self, report_id, as_zip=False):
def download_report(self, report_id: int) -> Tuple[str, str]:
"""Download a report
API Endpoint: GET /report/{id}
Expand All @@ -62,29 +64,28 @@ def download_report(self, report_id, as_zip=False):
>>>
>>> # Generate a report for upload 1
>>> report_id = foss.generate_report(foss.detail_upload(1))
>>> report_content = foss.download_report(report_id, as_zip=True)
>>> with open(filename, "w+") as report_file:
>>> report_content, report_name = foss.download_report(report_id)
>>> with open(report_name, "w+") as report_file:
>>> report_file.write(report_content)
:param report_id: the id of the generated report
:param as_zip: control if the report should be generated as ZIP file (default False)
:type report_id: int
:type as_zip: boolean
:return: the report content and the report name
:rtype: Tuple[str, str]
:raises FossologyApiError: if the REST call failed
:raises TryAgain: if the report generation timed out after 3 retries
"""
if as_zip:
headers = {"Accept": "application/zip"}
else:
headers = {"Accept": "text/plain"}

response = self.session.get(f"{self.api}/report/{report_id}", headers=headers)
response = self.session.get(f"{self.api}/report/{report_id}")
if response.status_code == 200:
return response.text
content = response.headers["Content-Disposition"]
report_name_pattern = '(^attachment; filename=")(.*)("$)'
report_name = re.match(report_name_pattern, content).group(2)
return response.text, report_name
elif response.status_code == 503:
wait_time = response.headers["Retry-After"]
logger.debug(f"Retry get report after {wait_time} seconds")
time.sleep(int(wait_time))
raise TryAgain
else:
description = "Download of report {report_id} failed"
description = f"Download of report {report_id} failed"
raise FossologyApiError(description, response)
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 = "0.1.4"
version = "0.2.0"
description = "A library to automate Fossology from Python scripts"
authors = ["Marion Deveaud <[email protected]>"]
license = "MIT License"
Expand Down
33 changes: 7 additions & 26 deletions tests/test_report.py
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@

from pathlib import Path
from test_base import foss, logger
from test_uploads import get_upload, do_upload, upload_filename
from test_uploads import get_upload, do_upload
from fossology.exceptions import FossologyApiError
from fossology.obj import ReportFormat

Expand All @@ -28,39 +28,20 @@ def test_generate_report(self):

try:
# Plain text
report = foss.download_report(report_id)
report_path = Path.cwd() / "tests/files"
report_name = upload_filename + ".spdx-report.rdf"
with open(report_path / report_name, "w+") as report_file:
report, name = foss.download_report(report_id)
report_path = Path.cwd() / "tests/files" / name
with open(report_path, "w+") as report_file:
report_file.write(report)

filetype = mimetypes.guess_type(report_path / report_name)
report_stat = os.stat(report_path / report_name)
filetype = mimetypes.guess_type(report_path)
report_stat = os.stat(report_path)
self.assertGreater(report_stat.st_size, 0, "Downloaded report is empty")
self.assertIn(
filetype[0],
("application/rdf+xml", "application/xml"),
"Downloaded report is not a RDF/XML file",
)
Path(report_path / report_name).unlink()
except FossologyApiError as error:
logger.error(error.message)

try:
# Zip
report = foss.download_report(report_id, as_zip=True)
report_path = Path.cwd() / "tests/files"
report_name = upload_filename + ".spdx-report.rdf.zip"
with open(report_path / report_name, "w+") as report_file:
report_file.write(report)

filetype = mimetypes.guess_type(report_path / report_name)
report_stat = os.stat(report_path / report_name)
self.assertGreater(report_stat.st_size, 0, "Downloaded report is empty")
self.assertEqual(
filetype[0], "application/zip", "Downloaded report is not a ZIP file"
)
Path(report_path / report_name).unlink()
Path(report_path).unlink()
except FossologyApiError as error:
logger.error(error.message)

Expand Down

0 comments on commit 04ca22d

Please sign in to comment.