Repository: yt-dlp/yt-dlp
File: youtube_dlc/downloader/external.py (Python)

Code before:
            for [i, url] in enumerate(info_dict['url_list']):
                tmpsegmentname = '%s_%s.frag' % (tmpfilename, i)
                file_list.append(tmpsegmentname)
            with open(tmpfilename, 'wb') as dest:
                for i in file_list:
                    if 'decrypt_info' in info_dict:
                        decrypt_info = info_dict['decrypt_info']
                        with open(i, 'rb') as src:
                            if decrypt_info['METHOD'] == 'AES-128':
                                iv = decrypt_info.get('IV')
                                decrypt_info['KEY'] = decrypt_info.get('KEY') or self.ydl.urlopen(
                                    self._prepare_url(info_dict, info_dict.get('_decryption_key_url') or decrypt_info['URI'])).read()
                                encrypted_data = src.read()
                                decrypted_data = AES.new(
                                    decrypt_info['KEY'], AES.MODE_CBC, iv).decrypt(encrypted_data)
                                dest.write(decrypted_data)
                            else:
                                shutil.copyfileobj(open(i, 'rb'), dest)
                    else:
                        shutil.copyfileobj(open(i, 'rb'), dest)
            if not self.params.get('keep_fragments', False):
                for file_path in file_list:
                    try:
                        os.remove(file_path)
                    except OSError as e:
                        print("Error: %s : %s" % (file_path, e.strerror))
                try:
                    file_path = '%s.frag.urls' % tmpfilename
                    os.remove(file_path)
                except OSError as e:
                    print("Error: %s : %s" % (file_path, e.strerror))

        return p.returncode

    def _prepare_url(self, info_dict, url):
        headers = info_dict.get('http_headers')
        return sanitized_Request(url, None, headers) if headers else url


class CurlFD(ExternalFD):
    AVAILABLE_OPT = '-V'

    def _make_cmd(self, tmpfilename, info_dict):
        cmd = [self.exe, '--location', '-o', tmpfilename]
        if info_dict.get('http_headers') is not None:
            for key, val in info_dict['http_headers'].items():
                cmd += ['--header', '%s: %s' % (key, val)]

        cmd += self._bool_option('--continue-at', 'continuedl', '-', '0')
        cmd += self._valueless_option('--silent', 'noprogress')
        cmd += self._valueless_option('--verbose', 'verbose')

Review comment (suggestion):
```suggestion
                        self.report_error("Unable to delete file %s; %s" % (file_path, error_to_compat_str(e))
```
Similar changes needed in other places.

The printing functions are `to_screen`, `report_warning` and `report_error`

Code after:
        if 'url_list' in info_dict:
            file_list = []
            for [i, url] in enumerate(info_dict['url_list']):
                tmpsegmentname = '%s_%s.frag' % (tmpfilename, i)
                file_list.append(tmpsegmentname)
            with open(tmpfilename, 'wb') as dest:
                for i in file_list:
                    if 'decrypt_info' in info_dict:
                        decrypt_info = info_dict['decrypt_info']
                        with open(i, 'rb') as src:
                            if decrypt_info['METHOD'] == 'AES-128':
                                iv = decrypt_info.get('IV')
                                decrypt_info['KEY'] = decrypt_info.get('KEY') or self.ydl.urlopen(
                                    self._prepare_url(info_dict, info_dict.get('_decryption_key_url') or decrypt_info['URI'])).read()
                                encrypted_data = src.read()
                                decrypted_data = AES.new(
                                    decrypt_info['KEY'], AES.MODE_CBC, iv).decrypt(encrypted_data)
                                dest.write(decrypted_data)
                            else:
                                shutil.copyfileobj(open(i, 'rb'), dest)
                    else:
                        shutil.copyfileobj(open(i, 'rb'), dest)
            if not self.params.get('keep_fragments', False):
                for file_path in file_list:
                    try:
                        os.remove(file_path)
                    except OSError as ose:
                        self.report_error("Unable to delete file %s; %s" % (file_path, error_to_compat_str(ose)))
                try:
                    file_path = '%s.frag.urls' % tmpfilename
                    os.remove(file_path)
                except OSError as ose:
                    self.report_error("Unable to delete file %s; %s" % (file_path, error_to_compat_str(ose)))

        return p.returncode

    def _prepare_url(self, info_dict, url):
        headers = info_dict.get('http_headers')
        return sanitized_Request(url, None, headers) if headers else url


class CurlFD(ExternalFD):
    AVAILABLE_OPT = '-V'

    def _make_cmd(self, tmpfilename, info_dict):
        cmd = [self.exe, '--location', '-o', tmpfilename]
        if info_dict.get('http_headers') is not None:
            for key, val in info_dict['http_headers'].items():
                cmd += ['--header', '%s: %s' % (key, val)]

        cmd += self._bool_option('--continue-at', 'continuedl', '-', '0')