<SYSTEM_TASK:>
Solve the following problem using Python, implementing the functions described below, one line at a time
<END_TASK>
<USER_TASK:>
Description:
 def download_all(self, products, directory_path='.', max_attempts=10, checksum=True):
 """Download a list of products. Takes a list of product IDs as input. This means that the return value of query() can be passed directly to this method. File names on the server are used for the downloaded files, e.g. "S1A_EW_GRDH_1SDH_20141003T003840_20141003T003920_002658_002F54_4DD1.zip". In case of interruptions or other exceptions, downloading will restart from where it left off. Downloading is attempted at most max_attempts times to avoid getting stuck with unrecoverable errors. Parameters products : list List of product IDs directory_path : string Directory where the downloaded files will be downloaded max_attempts : int, optional Number of allowed retries before giving up downloading a product. Defaults to 10. checksum : bool, optional If True, verify the downloaded files' integrity by checking its MD5 checksum. Throws InvalidChecksumError if the checksum does not match. Defaults to True. Raises ------ Raises the most recent downloading exception if all downloads failed. Returns ------- dict[string, dict] A dictionary containing the return value from download() for each successfully downloaded product. dict[string, dict] A dictionary containing the product information for products whose retrieval from the long term archive was successfully triggered. set[string] The list of products that failed to download. """

        product_ids = list(products)
        self.logger.info("Will download %d products", len(product_ids))
        return_values = OrderedDict()
        last_exception = None
        for i, product_id in enumerate(products):
            for attempt_num in range(max_attempts):
                try:
                    product_info = self.download(product_id, directory_path, checksum)
                    return_values[product_id] = product_info
                    break
                except (KeyboardInterrupt, SystemExit):
                    raise
                except InvalidChecksumError as e:
                    last_exception = e
                    self.logger.warning(
                        "Invalid checksum. The downloaded file for '%s' is corrupted.", product_id)
                except SentinelAPILTAError as e:
                    last_exception = e
                    self.logger.exception("There was an error retrieving %s from the LTA", product_id)
                    break
                except Exception as e:
                    last_exception = e
                    self.logger.exception("There was an error downloading %s", product_id)
            self.logger.info("%s/%s products downloaded", i + 1, len(product_ids))
        failed = set(products) - set(return_values)

        # split up sucessfully processed products into downloaded and only triggered retrieval from the LTA
        triggered = OrderedDict([(k, v) for k, v in return_values.items() if v['Online'] is False])
        downloaded = OrderedDict([(k, v) for k, v in return_values.items() if v['Online'] is True])

        if len(failed) == len(product_ids) and last_exception is not None:
            raise last_exception
        return downloaded, triggered, failed