@@ -65,12 +65,21 @@ def generate_report(
6565 description = f"Report generation for upload { upload .uploadname } failed"
6666 raise FossologyApiError (description , response )
6767
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 ]:
7072 """Download a report
7173
7274 API Endpoint: GET /report/{id}
7375
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+
7483 :Example:
7584
7685 >>> from fossology import Fossology
@@ -79,19 +88,22 @@ def download_report(self, report_id: int, group: str = None) -> Tuple[str, str]:
7988 >>>
8089 >>> # Generate a report for upload 1
8190 >>> 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
8393 >>> with open(report_name, "wb") as report_file:
8494 ... report_file.write(report_content) # doctest: +SKIP
8595
8696 :param report_id: the id of the generated report
8797 :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)
8899 :type report_id: int
89100 :type group: string
101+ :type wait_time: int
90102 :return: the report content and the report name
91103 :rtype: Tuple[str, str]
92104 :raises FossologyApiError: if the REST call failed
93105 :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
95107 """
96108 headers = dict ()
97109 if group :
@@ -100,17 +112,20 @@ def download_report(self, report_id: int, group: str = None) -> Tuple[str, str]:
100112 response = self .session .get (f"{ self .api } /report/{ report_id } " , headers = headers )
101113 if response .status_code == 200 :
102114 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 )
105117 return response .content , report_name
106118 elif response .status_code == 403 :
107119 description = (
108120 f"Getting report { report_id } { get_options (group )} not authorized"
109121 )
110122 raise AuthorizationError (description , response )
111123 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+ )
114129 time .sleep (int (wait_time ))
115130 raise TryAgain
116131 else :
0 commit comments