atlassian-python-api icon indicating copy to clipboard operation
atlassian-python-api copied to clipboard

_get_paged() in Confluence does not wrap exceptions as it should.

Open stevecj opened this issue 2 years ago • 2 comments

In get_page_child_by_type, we have

        try:                                                                            
            if not self.advanced_mode and start is None and limit is None:              
                return self._get_paged(url, params=params)                              
            else:                                                                       
                response = self.get(url, params=params)                                 
                if self.advanced_mode:                                                  
                    return response                                                     
                return response.get("results")                                          
        except HTTPError as e:                                                          
            if e.response.status_code == 404:                                           
                # Raise ApiError as the documented reason is ambiguous                  
                raise ApiError(                                                         
                    "There is no content with the given id, "                           
                    "or the calling user does not have permission to view the content", 
                    reason=e,                                                           
                )                                                                       
                                                                                        
            raise                                                                       

but return self._get_paged(url, params=params) returns a generator before it executes any code, and then it is executed in the context if iteration and does not have its exceptions handled through the try block. I an willing to write a fix for this and submit an MR but would like to discuss the approach first.

My first thought is to do define some functions within the method, something like the following (typing here, untested)

        def request_non_paged():
            response = self.get(url, params=params)                                 
            if self.advanced_mode:                                                  
                return response                                                     
            return response.get("results")

    def handle_exception_for(fn):
        try:
            fn()
        except HTTPError as e:                                                          
            if e.response.status_code == 404:                                           
                # Raise ApiError as the documented reason is ambiguous                  
                raise ApiError(                                                         
                    "There is no content with the given id, "                           
                    "or the calling user does not have permission to view the content", 
                    reason=e,                                                           
                )
                                                                                        
            raise                                                                       

        if not self.advanced_mode and start is None and limit is None:              
            return self._get_paged(url, params=params, err_handler=handle_exception_for)                              
        else:
            handle_exception_for(request_non_paged)

and then also modify _get_paged to accept the err_handler argument and execute its main body through that.

Opinions?

stevecj avatar Jun 20 '22 19:06 stevecj

Following code should also work:

            if not self.advanced_mode and start is None and limit is None:              
                for entry in self._get_paged(url, params=params):
                    yield entry                              

Spacetown avatar Jun 20 '22 20:06 Spacetown

Ah. Yes. Much simpler. Not sure why I didn't think of that. :)

stevecj avatar Jun 20 '22 23:06 stevecj