@@ -65,12 +65,21 @@ def generate_report(
65
65
description = f"Report generation for upload { upload .uploadname } failed"
66
66
raise FossologyApiError (description , response )
67
67
68
- @retry (retry = retry_if_exception_type (TryAgain ), stop = stop_after_attempt (3 ))
69
- def download_report (self , report_id : int , group : str = None ) -> Tuple [str , str ]:
68
+ @retry (retry = retry_if_exception_type (TryAgain ), stop = stop_after_attempt (10 ))
69
+ def download_report (
70
+ self , report_id : int , group : str = None , wait_time : int = 0
71
+ ) -> Tuple [str , str ]:
70
72
"""Download a report
71
73
72
74
API Endpoint: GET /report/{id}
73
75
76
+ Get report for a given upload. If the report is not ready wait another ``wait_time`` seconds or look at
77
+ the ``Retry-After`` to determine how long the wait period shall be.
78
+
79
+ If ``wait_time`` is 0, the time interval specified by the ``Retry-After`` header is used.
80
+
81
+ The function stops trying after **10 attempts**.
82
+
74
83
:Example:
75
84
76
85
>>> from fossology import Fossology
@@ -79,19 +88,22 @@ def download_report(self, report_id: int, group: str = None) -> Tuple[str, str]:
79
88
>>>
80
89
>>> # Generate a report for upload 1
81
90
>>> report_id = foss.generate_report(foss.detail_upload(1)) # doctest: +SKIP
82
- >>> report_content, report_name = foss.download_report(report_id) # doctest: +SKIP
91
+ >>> # Wait up to 20 Minutes until the report is ready
92
+ >>> report_content, report_name = foss.download_report(report_id, wait_time=120) # doctest: +SKIP
83
93
>>> with open(report_name, "wb") as report_file:
84
94
... report_file.write(report_content) # doctest: +SKIP
85
95
86
96
:param report_id: the id of the generated report
87
97
:param group: the group name to choose while downloading a specific report (default: None)
98
+ :param wait_time: use a customized upload wait time instead of Retry-After (in seconds, default: 0)
88
99
:type report_id: int
89
100
:type group: string
101
+ :type wait_time: int
90
102
:return: the report content and the report name
91
103
:rtype: Tuple[str, str]
92
104
:raises FossologyApiError: if the REST call failed
93
105
:raises AuthorizationError: if the user can't access the group
94
- :raises TryAgain: if the report generation timed out after 3 retries
106
+ :raises TryAgain: if the report generation times out after 10 retries
95
107
"""
96
108
headers = dict ()
97
109
if group :
@@ -100,17 +112,20 @@ def download_report(self, report_id: int, group: str = None) -> Tuple[str, str]:
100
112
response = self .session .get (f"{ self .api } /report/{ report_id } " , headers = headers )
101
113
if response .status_code == 200 :
102
114
content = response .headers ["Content-Disposition" ]
103
- report_name_pattern = ' (^attachment; filename=")(. *)("$)'
104
- report_name = re .match (report_name_pattern , content ).group (2 )
115
+ report_name_pattern = " (^attachment; filename=)( \" |')?([^ \" |'] *)(\" |'$)?"
116
+ report_name = re .match (report_name_pattern , content ).group (3 )
105
117
return response .content , report_name
106
118
elif response .status_code == 403 :
107
119
description = (
108
120
f"Getting report { report_id } { get_options (group )} not authorized"
109
121
)
110
122
raise AuthorizationError (description , response )
111
123
elif response .status_code == 503 :
112
- wait_time = response .headers ["Retry-After" ]
113
- logger .debug (f"Retry get report after { wait_time } seconds" )
124
+ if not wait_time :
125
+ wait_time = response .headers ["Retry-After" ]
126
+ logger .debug (
127
+ f"Retry GET report { report_id } after { wait_time } seconds: { response .json ()['message' ]} "
128
+ )
114
129
time .sleep (int (wait_time ))
115
130
raise TryAgain
116
131
else :
0 commit comments